按 tapply 函数的结果过滤数据框

Filter data frame by results from tapply function

我正在尝试应用我编写的 tapply 函数来过滤数据集。下面是一个示例数据框 (df),用于描述我正在尝试做的事情。

我想在我的数据框中保留 df$Cumulative_Time 的值最接近 14 的行。它应该为 each 执行此操作df$ID 中的因子级别(对于每个 ID 因子,使行最接近值 14)。

ID  Date    Results TimeDiff    Cumulative_Time
A   7/10/2015   71  0   0
A   8/1/2015    45  20  20
A   8/22/2015   0   18  38
A   9/12/2015   79  17  55
A   10/13/2015  44  26  81
A   11/27/2015  98  37  118
B   7/3/2015    75  0   0
B   7/24/2015   63  18  18
B   8/21/2015   98  24  42
B   9/26/2015   70  30  72
C   8/15/2015   77  0   0
C   9/2/2015    69  15  15
C   9/4/2015    49  2   17
C   9/8/2015    88  2   19
C   9/12/2015   41  4   23
C   9/19/2015   35  6   29
C   10/10/2015  33  18  47
C   10/14/2015  31  3   50
D   7/2/2015    83  0   0
D   7/28/2015   82  22  22
D   8/27/2015   100 26  48
D   9/17/2015   19  17  65
D   10/8/2015   30  18  83
D   12/9/2015   96  51  134
D   1/6/2016    30  20  154
D   2/17/2016   32  36  190
D   3/19/2016   42  27  217

我得到的结果如下:

spec_day = 14  # value I want to compare df$Cumulative_Time to


# applying function to calculate closest value to spec_day
    tapply(df$Cumulative_Time, df$ID, function(x) which(abs(x - spec_day) == min(abs(x - spec_day))))

问题:如何包含此 tapply 函数作为过滤数据框 df 的方法?我是在以正确的方式解决这个问题,还是有一些我没有看到的更简单的方法来完成这个问题?任何帮助将不胜感激--谢谢!

这里有一个方法可以做到,注意我没有使用 tapply:

spec_day <- 14
new_df <- do.call('rbind', 
            by(df, df$ID, 
            FUN = function(x) x[which.min(abs(x$Cumulative_Time - spec_day)), ]
              ))
new_df

  ID      Date Results TimeDiff Cumulative_Time
A  A  8/1/2015      45       20              20
B  B 7/24/2015      63       18              18
C  C  9/2/2015      69       15              15
D  D 7/28/2015      82       22              22

which.min(及其兄弟which.max)是一个非常有用的函数。

这是使用 data.table 的更简洁、更快速的替代方法:

library(data.table)
setDT(df)[, .SD[which.min(abs(Cumulative_Time - 14))], by = ID]
#   ID      Date Results TimeDiff Cumulative_Time
#1:  A  8/1/2015      45       20              20
#2:  B 7/24/2015      63       18              18
#3:  C  9/2/2015      69       15              15
#4:  D 7/28/2015      82       22              22