R data.table 中缺失值的高效移位

Effcient shifting in R data.table with missing values

我有一个 data.table 具有以下三个变量

  1. receptionist = 接待人员id
  2. week.no = 本周的数字(1 表示第一周)
  3. absent.thisweek = 本周缺席天数

请注意,我们只有接待员来上班的那几周的数据,如果缺少一周,则表示该人该周不在

例如,我们有两个接待处 1 和 2,工作模式如下:

dt <- data.table(receptionist =  c(1,1,1,2,2,2,2), week.no = c(1,3,4,5,8,10,11), absent.thisweek = c(1,2,3,4,5,6,6))
>dt receptionist week.no absent.thisweek
1:            1       1               1
2:            1       3               2
3:            1       4               3
4:            2       5               4
5:            2       8               5
6:            2      10               6
7:            2      11               6

第 1 步:我需要找出下周接待员缺席的天数,为此我将 absent.thisweek 移动一周(如果该信息在数据中可用),请注意这几周接待员还没来,这个值将是 NA,我的数据集有 100 万行,这是效率最低的部分。

dt[order(receptionist, week.no), absent.nextweek := dt$absent.thisweek[dt$receptionist==receptionist & dt$week.no==week.no+1], by = .(receptionist, week.no)]
>dt receptionist week.no absent.thisweek absent.nextweek
1:            1       1               1              NA
2:            1       3               2               3
3:            1       4               3              NA
4:            2       5               4              NA
5:            2       8               5              NA
6:            2      10               6               6
7:            2      11               6              NA

第 2 步:如果数据缺失,则必须缺席 7 天。在上周,我们将有 absent.nextweek = NA

dt[is.na(absent.nextweek) & week.no != max(week.no, na.rm=T), absent.nextweek:=7]
   
>dt receptionist week.no absent.thisweek absent.nextweek
1:            1       1               1               7
2:            1       3               2               3
3:            1       4               3               7
4:            2       5               4               7
5:            2       8               5               7
6:            2      10               6               6
7:            2      11               6              NA

我面临两个问题: -在第 1 步中,它非常低效并且需要很长时间(大约一个小时)才能 运行 - 在步骤 2 中,第 3 行的最后一列应该有 NA,但事实并非如此

任何提高效率的建议(最好是data.table)都会非常有帮助并指出步骤2中的错误。

正确答案是:

>dt receptionist week.no absent.thisweek absent.nextweek
1:            1       1               1               7
2:            1       3               2               3
3:            1       4               3               NA
4:            2       5               4               7
5:            2       8               5               7
6:            2      10               6               6
7:            2      11               6              NA

从头开始思考这个问题,也许你可以直接用 fifelse()shift()?

# We assume data is ordered by week. Otherwise you can run 
# setorder(dt, receptionist, week.no)

dt[, 
   absent.nextweek := 
     fifelse(week.no+1L == shift(week.no, -1L),  shift(absent.thisweek, -1L), 7),
   by = receptionist]


#    receptionist week.no absent.thisweek absent.nextweek
# 1:            1       1               1               7
# 2:            1       3               2               3
# 3:            1       4               3              NA
# 4:            2       5               4               7
# 5:            2       8               5               7
# 6:            2      10               6               6
# 7:            2      11               6              NA