2017-02-16 28 views
1

中,我有一個unbalaned板公司的數據如下:找到最接近的競爭對手組

time   comid group  sales   closeone 
1988m1  tw1701  1  2.45    tw1410 
1988m1  tw1213  1  1.98    tw1701 
1988m1  tw1707  1  2.67   
1988m1  tw2702  1  9.45   
1988m1  tw9902  1  4.16   
1988m1  tw1410  1  2.57   
1988m2  tw2601  3  27.44   tw2505 
1988m2  tw2505  3  9.49   
1988m2  tw1413  3  1.46   
1988m2  tw2901  3  3.74   
1988m2  tw1417  4  1.87    tw1506  
1988m2  tw1506  4  3.24   
1988m2  tw1215  4  3.58 

我的目的是要找出同一組和時間內最接近的對手。

就像列colseone顯示。例如,

所述closeone第一行中

,tw1410是下組= 1,時間= 1988m1條件,

ABS(所有銷售 - 銷售tw1701的),並找到最小值和排除零(即可以」本身)。

回答

1

我不確定你爲什麼被低估,我不認爲這是微不足道的。這是我解決它的方式。可能有一個更簡單的方法。我無法獲取data.table操作來設置最終值,因此必須使用for循環。

基本上它按組對數據進行排序,計算同一組內的上下行之間的差異,找到這兩個值的最小值,然後通過該引用設置競爭對手的值。

library(data.table) 
setDT(dat) 
setorder(dat,time,group,-sales) 

dat[ , "Diff" := c(NA, diff(sales)), by = .(time,group)] 
dat[ , "Diff2" := c(diff((sales)),NA), by = .(time,group)] 


dat[ ,"Min" := ifelse(abs(Diff) < abs(Diff2), 1, 2)] 
dat[ ,"Min" := ifelse(is.na(Diff),2,Min)] 
dat[ ,"Min" := ifelse(is.na(Diff2),1,Min)] 

dat[, "Rival" := NA] 

for(i in 1:nrow(dat)){ 
    if(dat$Min[i] == 2){ 
    dat$Rival[i] = as.character(dat[i+1,comid]) 
    }else{ 
    dat$Rival[i] = as.character(dat[i-1,comid]) 
    } 
} 

> dat 
     time comid group sales Diff Diff2 Min Rival 
1: 1988m1 tw2702  1 9.45  NA -5.29 2 tw9902 
2: 1988m1 tw9902  1 4.16 -5.29 -1.49 2 tw1707 
3: 1988m1 tw1707  1 2.67 -1.49 -0.10 2 tw1410 
4: 1988m1 tw1410  1 2.57 -0.10 -0.12 1 tw1707 
5: 1988m1 tw1701  1 2.45 -0.12 -0.47 1 tw1410 
6: 1988m1 tw1213  1 1.98 -0.47  NA 1 tw1701 
7: 1988m2 tw2601  3 27.44  NA -17.95 2 tw2505 
8: 1988m2 tw2505  3 9.49 -17.95 -5.75 2 tw2901 
9: 1988m2 tw2901  3 3.74 -5.75 -2.28 2 tw1413 
10: 1988m2 tw1413  3 1.46 -2.28  NA 1 tw2901 
11: 1988m2 tw1215  4 3.58  NA -0.34 2 tw1506 
12: 1988m2 tw1506  4 3.24 -0.34 -1.37 1 tw1215 
13: 1988m2 tw1417  4 1.87 -1.37  NA 1 tw1506 

如果有人有更好的解決方案,我很樂意看到它。

編輯

我之所以不能進入矢量格式這顯然是因爲comid是一個因素。我不知道爲什麼會打破這個功能,但是當我將它改成字符時它就起作用了。

這種替換for循環:

dat$comid = as.character(dat$comid) 
dat[, "Rival" := ifelse(Min == 2, shift(comid, type = "lead"), shift(comid, type = "lag"))] 

> dat 
     time comid group sales Diff Diff2 Min Rival 
1: 1988m1 tw2702  1 9.45  NA -5.29 2 tw9902 
2: 1988m1 tw9902  1 4.16 -5.29 -1.49 2 tw1707 
3: 1988m1 tw1707  1 2.67 -1.49 -0.10 2 tw1410 
4: 1988m1 tw1410  1 2.57 -0.10 -0.12 1 tw1707 
5: 1988m1 tw1701  1 2.45 -0.12 -0.47 1 tw1410 
6: 1988m1 tw1213  1 1.98 -0.47  NA 1 tw1701 
7: 1988m2 tw2601  3 27.44  NA -17.95 2 tw2505 
8: 1988m2 tw2505  3 9.49 -17.95 -5.75 2 tw2901 
9: 1988m2 tw2901  3 3.74 -5.75 -2.28 2 tw1413 
10: 1988m2 tw1413  3 1.46 -2.28  NA 1 tw2901 
11: 1988m2 tw1215  4 3.58  NA -0.34 2 tw1506 
12: 1988m2 tw1506  4 3.24 -0.34 -1.37 1 tw1215 
13: 1988m2 tw1417  4 1.87 -1.37  NA 1 tw1506 

應該運行速度快了很多。

+0

我得到了「替換長度爲零」的消息,所以我改爲以2: 開始(我在2:nrow(dat))。那麼它的工作。順便提一句,數據有3萬個obs,它運行很長。如果我提取一些obs作爲實驗組並匹配流行音樂,該怎麼辦? samp <-dat [(3,7,8,9),] dplyr :: left_join(samp,pop,by = c(「comid」,「time)) 會不會耗時在實驗組中找到最接近的競爭對手ref。 – changjx

+0

@changjx所有的data.table操作都應該立即完成,for循環是否很慢?我可以嘗試修復該部分。 0再次檢查for循環中的+/- i可能會倒退 – Kristofersen

+0

@changjx所以再考慮一下我認爲我們可以使用data.table中的shift來代替for循環,我可以在明天玩這個遊戲。 – Kristofersen