重复将条件摘要应用于数据框中的组

时间:2019-07-18 02:19:22

标签: r dplyr data.table

我有一个看起来像这样的大数据框:

group_id    distance    metric
       1         1.1      0.85
       1         1.1      0.37
       1         1.7      0.93   
       1         2.3      0.45 
       ...
       1         6.3      0.29
       1         7.9      0.12
       2         2.5      0.78
       2         2.8      0.32
       ...

数据框已按group_id,然后按distance排序。我想知道dplyr或data.table等效于执行以下操作:

在每个group_id中:

  1. 将当前distancegroup_id的唯一值和排序后的值设为d1,d2,...,d_n
  2. 对于d中的每个d1,d2,...,d_n:对f小于metric的{​​{1}}的所有值计算一些函数distance。函数d是一个自定义的用户定义函数,它接受一个向量并返回一个标量。假设函数f在空向量上定义良好。

因此,在上面的示例中,所需的数据帧如下所示:

f

请注意如何重复group_id distance_less_than metric 1 1.1 f(empty vector) 1 1.7 f(0.85, 0.37) 1 2.3 f(0.85, 0.37, 0.93) ... 1 7.9 f(0.85, 0.37, 0.93, 0.45,...,0.29) 2 2.5 f(empty vector) 2 2.8 f(0.78) ... 的值,例如组distance下的值1.1。在这种情况下,当距离小于1时,应排除这两行(在这种情况下,这将导致空向量)。

2 个答案:

答案 0 :(得分:5)

一种可能的方法是使用data.table中可用的非等额联接。左表是group_id和distance的唯一组合,而右表的距离都小于左表的距离。

f <- sum
DT[unique(DT, by=c("group_id", "distance")), on=.(group_id, distance<distance), allow.cartesian=TRUE,
    f(metric), by=.EACHI]

输出:

   group_id distance   V1
1:        1      1.1   NA
2:        1      1.7 1.22
3:        1      2.3 2.15
4:        1      6.3 2.60
5:        1      7.9 2.89
6:        2      2.5   NA
7:        2      2.8 0.78

数据:

library(data.table)
DT <- fread("group_id    distance    metric
1         1.1      0.85
1         1.1      0.37
1         1.7      0.93   
1         2.3      0.45 
1         6.3      0.29
1         7.9      0.12
2         2.5      0.78
2         2.8      0.32")

答案 1 :(得分:1)

不要认为这比data.table选项要快,但这是使用dplyr的一种方法

library(dplyr)

df %>%
  group_by(group_id) %>%
  mutate(new = purrr::map_dbl(distance, ~f(metric[distance < .])))

其中f是您的功能。 map_dbl期望函数的返回类型为double。如果您的函数具有不同的返回类型,则可能要使用map_intmap_chr等。

如果每个distance仅保留一个条目,则可以使用filterduplicated

删除它们
df %>%
  group_by(group_id) %>%
  mutate(new = purrr::map_dbl(distance, ~f(metric[distance < .]))) %>%
  filter(!duplicated(distance))