bigdata_lab1

advertisement
Нижегородский Государственный Технический Университет
им. Р.Е.Алексеева
Кафедра «Вычислительные системы и технологии»
Отчет
по дисциплине: Основы предиктивной аналитики
«Анализ данных мобильного оператора. Поиск пути. Поиск владельца устройств.»
Выполнил:
студент группы М14-ИВТ-3
Сидоренко О.О.
Проверил:
Крылов В.В.
Нижний Новгород
2015 год
Задание.
По заданным исходным данным вывести на карты путь для каждого устройства и определить
такие пары устройств, которые принадлежат одному человеку.
Вывод пути для каждого устройства
Для вывода путей для всех устройств на карту необходим следующий минимальный набор
данных:
 Идентификатор устройства
 Географичческие координаты точек-отметок
 Показатель последовательности точек-отметок
Учитывая исходные данные можно обозначить за идентификатор устройства поле с IMEI, за
показатель последовательности поле tstamp. А географически координаты точек-отметок
устройства представлены несколько иначе: в исходных данных нет точного местоположения
устройства в каждый момент времени, однако есть географические координаты вышки связи, где
зарегистрировалось устройство в определенный момент времени, а также радиус действия
вышки и начальный и конечный углы окружности с центром – вышкой. Т.о. можно получить
сектор, где точно находится абонент (устройство) и вычислив центр масс этого сектора получим
более точное расположение устройства.
Перед работой вывода исходные данные, представленные в таблице, сортируются по времени; в
отдельный объект выносятся все имеющиеся идентификаторы устройств; рассчитываются
географические координаты центров масс секторов, о которых сказано выше. Далее для каждого
устройства идет обращения к сервису Google Maps для получения изображения карты местности
и затем последовательно на карту наносятся географические координаты центров масс секторов
и проводятся к ним стрелки.
В итоге получается набор изображений, подобных рис.1
Рис.1 Путь устройства
2
Определение пар устройств.
Из тех данных, что имеются по условию, для определения пары устройств (далее ПУ),
принадлежащих одному владельцу, разумным видится использование путей, которые прошли
эти устройства.
Существует несколько способов найти ПУ, используя пути, но все они основываются на том, что
пути каждого устройства должны более-менее совпадать. Таким образом, необходимо найти
некий показатель для каждого пути, который будет критерием выбора при объединении путей в
группу. Этот показатель может быть представлен не одним значением, а несколькими. Так,
например, можно определить ПУ, находя пути, где вышки (т.е. и центры масс их секторов)
расположены очень близко друг к другу или совпадают. Однако в данной работе используется
несколько показателей, представленных каждый одним значением, это Среднее и Время.
Рассмотрим их подробнее:
 Среднее – среднее арифметическое значение по одной из географических координат всех
центров масс секторов вышек на пути. Этот показатель очень грубо отсеивает пути, т.к.
возможно существуют пути с близкими средними, но один из путей либо расположен
«вокруг» другого, либо направлен в обратную сторону, либо включает в себя другой путь.
Пример на рис.2, 3 – оба пути имеют приблизительно одинаковое Среднее, но физически
не могут совершаться одним и тем же абонентом в одно и то же время.
 Время – разница между временем регистрации на первой вышки пути и временем
регистрации на последней вышке. Если устройства принадлежат одному абоненту, и он
использует их параллельно, то время регистрации на крайних вышках, и, следовательно,
время всего пути, будет приблизительно равным. Однако при использовании этого
показателя резко отбрасываются такие варианты, где путь в одну сторону абонент прошел
с одним устройством, а в обратную – с другим. Или где этот путь совершался одним и тем
же абонентом с разными устройствами, но в два разных дня. Аналогично Среднему, этот
показатель пропускает разнонаправленные пути.
Рис.2
Рис.3
Для сравнения показателей между собой необходимо определить какую-либо погрешность
позволяющую определить промежуток, в которую должен входить показатель. Для этого можно
ввести т.н. «степень схожести» двух чисел – показатель, не имеющий под собой физического
смысла, лишь численно определяющий насколько одно из чисел близко к другому. В
дальнейшем достаточно будет сравнить «степень схожести» с каким либо порогом.
Сам алгоритм достаточно прост: после определения показателей необходимо разделить пути на
группы, используя сравнение с порогом, а после прохождения нескольких порогов можно будет
дать результат. Сравним полученные результаты при использовании только одного показателя
(Среднее) с результатами при использовании двух показателей подряд.
Т.к. приблизительные ответы уже были предоставлены, то достаточно будет найти общие ПУ
между полученными результатами и ответами.
Результаты сравнения приведены в таблице 1.
3
Таблица 1. Решение задачи
Использованные
Порог
показатели
Среднее
0.99999
Среднее; Время
0.99999
Среднее
0.9999
Среднее; Время
0.9999
Найдено ПУ
34
1
1049
2
Совпало с
ответом
1
0
18
Часть ответа
158530782111
158520030347
158515687371
158515687709
158500730487
158500730293
158524011029
158515590685
158526303217
158526252825
158537942677
158522930839
158506092285
158501557263
158530782111
158520030347
0
Как видно, такой алгоритм показал не лучшие результаты, но сработал – можно говорить о том,
что одна ПУ точно была найдена. Однако, заменив сравнение «степени схожести» на
классическое определение попадания в промежуток можно изменить результат.
Таблица 2. Решение задачи альтернативным способом: без «степени схожести»
Использованные
Порог
Найдено ПУ
Совпало с
Часть ответа
показатели
ответом
158515687371
Среднее
0.01
4707
30
158515687709
158514437601
158507135235
158529952561
158529633307
158500730487
158500730293
158524011029
158515590685
158526303217
158526252825
158516497707
158500941403
158537942677
158522930839
158506092285
158501557263
158598060279
158533714541
158507689477
158526742489
158520675947
158536558521
158530782111
158520030347
158529027621
158500411793
Среднее; Время
0.01;1000000
111
1
В данном случае увеличилось количество ответов в обоих случаях, однако увеличилось и
количество найденных ПУ. Это говорит о том, что необходимо более точно выставлять пороги.
4
Вывод
Из двух заданий было успешно выполнено только первое – вывод пути на карту.
Второе задание вызвало затруднения из-за нехватки данных и, как следствие, из-за отсутствия
грамотно поставленных условий отсева результатов. Однако на заданных данных алгоритм
сработал достаточно верно.
5
Приложение
library(ggmap)
library(mapproj)
library(RgoogleMaps)
library(maptools)
library(rgdal)
library(sp)
data_mobile<-read.csv(file = "02_Data_mobile.csv",sep = ";", header = TRUE)
na.omit(data_mobile)# проверили на NA
data_sort<-data_mobile[order(data_mobile$tstamp),] #отсортировали по таймштампу
#plot(data_sort$long ~ data_sort$lat,pch=19,type="o",col=data_sort$imei, xlab="Lat",ylab="Long")
all_imei<-data.frame(imei = data_sort$imei) #вытащили все имеи
#убрали одинаковые имеи, null и пустые строки. Тут null как текст будет, поэтому и убираем
all_imei<-subset(all_imei,!duplicated(all_imei$imei) & all_imei$imei!="null" & all_imei$imei!="")
attach(data_sort)#чтобы не использовать длинное обращение к элементу
#Определили нулевые координаты
startY <- long[1]
startX <- lat[1]
#Рассчитали ГЕОМЕТРИЧЕСКИЕ координаты вышек. в км
data_sort$oldY <- 6371*sin(long-startY)
data_sort$oldX <- 6371*sin(lat-startX)
#рассчитали геометрические координаты центров секторов около вышек
data_sort$Y <- data_sort$oldY + (2/3)*0.001*max_dist*2*sin(0.5*abs(end_angle-start_angle))*cos(start_angle+0.5*abs(end_anglestart_angle))/(abs(end_angle-start_angle)*pi/180)
data_sort$X <- data_sort$oldX + (2/3)*0.001*max_dist*2*sin(0.5*abs(end_angle-start_angle))*sin(start_angle+0.5*abs(end_anglestart_angle))/(abs(end_angle-start_angle)*pi/180)
#рассчитали ГЕОГРАФИЧЕСКИЕ координаты центров секторов около вышек
data_sort$longMID <- asin(data_sort$Y/6371)+startY
data_sort$latMID <- asin(data_sort$X/6371)+startX
data_sort<-subset(data_sort,longMID > 0 & latMID > 0 )
na.omit(data_sort)
#Рисуем пути
for(j in 1:20) #nrow(all_imei))
{
data_imei<-data_sort[data_sort$imei==all_imei$imei[j],]
na.omit(data_imei)
lonlat<-data.frame(lon = data_imei$longMID,lat = data_imei$latMID)
data_imei_uniq<-lonlat[!duplicated(lonlat),]#unique(lonlat)
data_imei_uniq<-subset(data_imei_uniq,lon > 0 & lat > 0)
mymap = MapBackground(lat=data_imei_uniq$lat,
lon=data_imei_uniq$lon,
zoom = 13,
NEWMAP = TRUE,
GRAYSCALE = FALSE,
)
PlotOnStaticMap(mymap,
data_imei_uniq$lat[1],
data_imei_uniq$lon[1],
cex=1.5,
pch=19,
col=c('red'),
add=FALSE
)
PlotOnStaticMap(mymap,
data_imei_uniq$lat[1],
data_imei_uniq$lon[1],
FUN=text,
labels = "First",
col=c('blue'),
add=TRUE
)
if(nrow(data_imei_uniq)>1)
{
6
for(i in 2:nrow(data_imei_uniq))
{
PlotOnStaticMap(mymap,
data_imei_uniq$lat[i],
data_imei_uniq$lon[i],
cex=1.5,
pch=19,
col=c('red'),
add=TRUE
)
PlotArrowsOnStaticMap(mymap,
lat0=data_imei_uniq$lat[i-1],
lon0=data_imei_uniq$lon[i-1],
lat1=data_imei_uniq$lat[i],
lon1=data_imei_uniq$lon[i],
col=c('blue'),
add=TRUE
)
}
}
setwd("D:/MyFiles/work/maps")
filename<-paste0("map",all_imei$imei[j],".png")
dev.print(png, width = 640, file = filename)
setwd("D:/MyFiles/work")
}
#Попробуем найти пары девайсов
#Функция выводит степень похожести двух чисел. Вообще не имеет физического смысла
Similarities = function (x, y)
{
if((x-y)==0) {result<-1}
else
{
result<-(x-y)/((x+y)/2)
result<-1-abs(result)
}
return(result)
}
#создадим фрейм со средними значениями путей для каждого IMEI и разницей таймштампов пути
all_imei_info<-data.frame()
for(i in 1:length(all_imei$imei))
{
lat_info<- data_sort$latMID[data_sort$imei == all_imei$imei[i]]
lon_info<- data_sort$longMID[data_sort$imei == all_imei$imei[i]]
tstamp <- max(data_sort$tstamp[data_sort$imei == all_imei$imei[i] & data_sort$tstamp>0])- min(data_sort$tstamp[data_sort$imei ==
all_imei$imei[i] & data_sort$tstamp>0])
all_imei_info<-rbind(all_imei_info,
data.frame(imei = all_imei$imei[i],
latMean = mean(lat_info),
lonMean = mean(lon_info),
time = tstamp
))
}
#попробуем выдрать пути
epsylon <- 0.01#точность приближения
epsylonTstamp <- 10000
relatePath<-data.frame()
for(i in 1:length(all_imei$imei))
{
#среднее значение пути для основного IMEI
latM_1<-all_imei_info$latMean[i] #[all_imei_info$imei == all_imei$imei[i]]
lonM_1<-all_imei_info$lonMean[i] #[all_imei_info$imei == all_imei$imei[i]]
for(j in i:length(all_imei))
{
if (j==i){ next }
#среднее значение пути для меняющегося IMEI
latM_2<-all_imei_info$latMean[j] #[all_imei_info$imei == all_imei$imei[j]]
lonM_2<-all_imei_info$lonMean[j] #[all_imei_info$imei == all_imei$imei[j]]
7
#Вычислим степень похожести средних значений путей.
measureSimil_lat<-Similarities(latM_1,latM_2)
measureSimil_lon<-Similarities(lonM_1,lonM_2)
if(measureSimil_lat<0.9999) {next}
if(measureSimil_lon<0.9999) {next}
#Альтернатива: если средния значения выходят за рамки, то выход на след итерацию
#if ((latM_2<latM_1-epsylon)||(latM_2>latM_1+epsylon)) { next }
#if ((lonM_2<lonM_1-epsylon)||(lonM_2>lonM_1+epsylon)) { next }
#Проверка на схожесть показателей дельта времени
firstTstamp_1 <- all_imei_info$time[i]
firstTstamp_2 <- all_imei_info$time[j]
compare<-Similarities(firstTstamp_1,firstTstamp_2)
if(compare<0.9999) {next}
#Альтернатива: если значения выходят за рамки, то выход на след итерацию
#if ((firstTstamp_2<firstTstamp_1-epsylonTstamp)
# ||(firstTstamp_2>firstTstamp_1+epsylonTstamp)) { next }
relatePath<-rbind(relatePath,data.frame(imei_1 = all_imei$imei[i],
imei_2 = all_imei$imei[j]
))
}
}
#выведем вместо imei msisdn
relatePath_msisdn<-data.frame()
for(i in 1:length(relatePath$imei_1))
{
msisdn_first <- data_sort$msisdn[data_sort$imei == relatePath$imei_1[i]][1]
msisdn_second <- data_sort$msisdn[data_sort$imei == relatePath$imei_2[i]][1]
relatePath_msisdn<-rbind(relatePath_msisdn, data.frame(msisdn_1 = msisdn_first,
msisdn_2 = msisdn_second))
}
#Запишем результаты в таблицу
write.table(relatePath_msisdn, file = "Result.csv", row.names = FALSE, sep=";")
#Выведем результаты данных ответов в подобный фрейм
RightAnswer_msisdn<-read.csv(file = "Answer.csv",sep = ";", header = FALSE)
#Выведем одинаковые значения между полученным и данным результами
result<-data.frame()
for(i in 1:length(relatePath_msisdn$msisdn_1))
{
for(j in 1:length(RightAnswer_msisdn$V1))
{
if(relatePath_msisdn$msisdn_1[i] == RightAnswer_msisdn$V1[j])
{
if(relatePath_msisdn$msisdn_2[i]!=RightAnswer_msisdn$V2[j]) {next}
}
else if(relatePath_msisdn$msisdn_1[i] == RightAnswer_msisdn$V2[j])
{
if(relatePath_msisdn$msisdn_2[i]!=RightAnswer_msisdn$V1[j]) {next}
}
else {next}
result<-rbind(result,data.frame(msisdn_1 = relatePath_msisdn$msisdn_1[i],
msisdn_2 = relatePath_msisdn$msisdn_2[i]
))
}
}
8
Download