我有一个看起来像这样的大数据框:
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
中:
distance
中group_id
的唯一值和排序后的值设为d1,d2,...,d_n
。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
时,应排除这两行(在这种情况下,这将导致空向量)。
答案 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_int
,map_chr
等。
如果每个distance
仅保留一个条目,则可以使用filter
和duplicated
df %>%
group_by(group_id) %>%
mutate(new = purrr::map_dbl(distance, ~f(metric[distance < .]))) %>%
filter(!duplicated(distance))