2017-07-31 29 views
0

大家好:我早些时候发布了,得到了80%的帮助,但希望为其他人开放与R中的which()函数类似的问题:哪个()函数在R - 按降序排序后,与重复值匹配的问题

我正试图从每个邮政编码的商店ID,邮政编码和长/纬度坐标矩阵中找到下一个最近的商店。每个邮政编码超过1个商店时会发生问题,并且脚本不知道如何订购2个相同的值(商店x距离10英里,存储y为10英里,并且遇到x和y,并返回(c(x,y)),而不是x,y或y,x)。我需要找到一种方法让我的代码弄清楚如何列出它们(阿根廷订单,因为它们距商店相同的距离,基于邮政编码)。

我在想那里可能会修改which()函数,但我没有任何运气。

请注意,所有的商店运行,只有100个左右的商店,与另一家商店有相同的邮编被绊倒了 - 我不想手动通过和编辑csv。

library(data.table) 
library(zipcode) 
library(geosphere) 
source<-read.csv("C:\\Users\\mcan\Desktop\\Projects\\Closest Store\\Site and Zip.csv",header=TRUE, sep=",") #open 
zip<-source[,2] #break apart the source zip codes 
ID<-source[,1] #break apart the IDs 
zip<-clean.zipcodes(zip) #clean up the zipcodes 
CleanedData<-data.frame(ID,zip) #combine the IDs and cleaned Zip codes 
CleanedData<-merge(x=CleanedData,y=zipcode,by="zip",all.x=TRUE) #dataset of store IDs, zipcodes, and their long/lat positions 
setDT(CleanedData) #set data frame to data table 
storeDistances <- distm(CleanedData[,.(longitude,latitude)],CleanedData[,.(longitude,latitude)]) #matrix between long/lat points of all stores in list 
colnames(storeDistances) <- rownames(storeDistances) <- CleanedData[,ID] 
whatsClosest <- function(number=1){ 
    apply(storeDistances,1,function(x) (colnames(storeDistances)[which(x==sort(x)[number+1])])) #sorts in descending order and picks the 2nd closest distance, matches with storeID 
} 
CleanedData[,firstClosestSite:=whatsClosest(1)] #looks for 1st closest store 
CleanedData[,secondClosestSite:=whatsClosest(2)] #looks for 2nd closest store 
CleanedData[,thirdClosestSite:=whatsClosest(3)] #looks for 3rd closest store 

数据集格式:

Classes ‘data.table’ and 'data.frame': 1206 obs. of 9 variables: 
    $ zip    : Factor w/ 1182 levels "","02345",..: 1 2 3 4 5 6 7 8 9 10 ... 
    $ ID    : int 11111 12222 13333 10528 ... 
    $ city    : chr "Boston" "Somerville" "Cambridge" "Weston" ... 
    $ state   : chr "MA" "MA" "MA" "MA" ... 
    $ latitude   : num 40.0 41.0 42.0 43.0 ... 
    $ longitude  : num -70.0 -70.1 -70.2 -70.3 -70.4 ... 
    $ firstClosestSite :List of 1206 
     ..$ : chr "12345" 
    $ secondClosestSite :List of 1206 
     ..$ : chr "12344" 
    $ thirdClosestSite :List of 1206 
     ..$ : chr "12343" 

问题自带firstClosestSite和secondClosest网站,他们按距离排序,但如果距离是相同的,因为在同一个邮政编码存在两种专卖店,其中()函数(我认为)不知道如何解决这个问题,所以你得到的CSV这种尴尬串联:

StoreID  Zip  City  State Longitude Latitude FirstClosestSite 
11222  11000  Boston  MA  40.0  -70.0 c("11111""12222") 

SecondClosestSite  ThirdClosestSite 
c("11111" "12222") 13333 

如何形成的距离矩阵示例(在第一行和列存储的ID,与矩阵值被存储的ID之间的距离):

11111 22222  33333 44444 55555 66666 
11111 0  6000 32000 36000 28000 28000 
22222 6000 0  37500 40500 32000 32000 
33333 32000 37500 0  11000 6900 6900 
44444 36000 40500 11000 0  8900 8900 
55555 28000 32000 6900 8900 0  0 
66666 28000 32000 6900 8900 0  0 

问题是每一行中的重复...的哪个()不知道哪个商店最接近到11111(55555或66666)。

+0

你能提供一个你的数据集样本和你正在寻找的最终结果吗? –

+0

@OriolMirosa刚刚编辑!例如,需要在站点11111或12222之间做出决定 - 通过CSV并修复这些行太麻烦了〜有什么想法? :P – mcando

+0

@OriolMirosa我正在寻找哪个()函数的替代方案 – mcando

回答

1

这是我的解决方案。一直到colnames(storeDistances) <- ...的行保持不变。在这之后,你应该替换为以下代码:

whatsClosestList <- sapply(as.data.frame(storeDistances), function(x) list(data.frame(distance = x, store = rownames(storeDistances), stringsAsFactors = F))) 

# Get the names of the stores 
# this step is necessary because lapply doesn't allow us 
# to access the list names 
storeNames = names(whatsClosestList) 

# Iterate through each store's data frame using storeNames 
# and delete the distance to itself 
whatsClosestListRemoveSelf <- lapply(storeNames, function(name) { 
    df <- whatsClosestList[[name]] 
    df <- df[!df$store == name,] 
}) 

# The previous step got rid of the store names in the list, 
# so we add them again here 
names(whatsClosestListRemoveSelf) <- storeNames 

whatsClosestOrderedList <- lapply(whatsClosestListRemoveSelf, function(df) { df[order(df$distance),] }) 

whatsClosestTopThree <- lapply(whatsClosestOrderedList, function(df) { df$store[1:3] }) 

firstClosestSite <- lapply(whatsClosestTopThree, function(x) { x[1]}) 
secondClosestSite <- lapply(whatsClosestTopThree, function(x) { x[2]}) 
thirdClosestSite <- lapply(whatsClosestTopThree, function(x) { x[3]}) 

CleanedData[,firstClosestSite:=firstClosestSite] #looks for 1st closest store in list 
CleanedData[,secondClosestSite:=secondClosestSite] #looks for 2nd closest store in list 
CleanedData[,thirdClosestSite:=thirdClosestSite] #looks for 3rd closest store in list 

基本上,而不是只对(第一,第二,第三)最近的站点搜索,我创建dataframes的列表一起的距离每家店所有其他商店。然后,我订购这些数据框,并提取最近的三家商店,这些商店有时包括关系(如果并列,则按商店名称排序)。然后,您只需要为每个商店提供第一个关闭网站,第二个关闭网站等的列表,这就是为什么您在CleanedData的搜索中使用的原因。希望它有效!

+0

是的,当我复制这个时,我忘记了等号。我很高兴它现在可以工作! –