找到组中最接近的对手

时间:2017-02-16 16:21:35

标签: r min

我有一个未实验的面板公司数据如下:

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所示。例如,

在第一行的第一行中,tw1410在group = 1下,时间= 1988m1条件,

abs(所有销售 - 销售额为tw1701)并找到最小值并排除零(即不能自己)。

1 个答案:

答案 0 :(得分: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

这应该运行得更快。