有没有类似于plyr::join_all的dplyr或data.table等效函数,能够通过数据框列表进行连接?与PLYR中join_all相同的功能。

8
考虑到这个 data.frame
set.seed(4)
df <- data.frame(x = rep(1:5, each = 2), y = sample(50:100, 10, T))
#    x  y
# 1  1 78
# 2  1 53
# 3  2 93
# 4  2 96
# 5  3 61
# 6  3 82
# 7  4 53
# 8  4 76
# 9  5 91
# 10 5 99

我希望编写一些简单的函数(即特征工程),为变量x创建特征,然后将每个生成的data.frame合并在一起。例如:

library(dplyr)
count_x <- function(df) df %>% group_by(x) %>% summarise(count_x = n())
sum_y   <- function(df) df %>% group_by(x) %>% summarise(sum_y = sum(y))
mean_y  <- function(df) df %>% group_by(x) %>% summarise(mean_y = mean(y))  
# and many more...

使用plyr::join_all可以实现这一目标,但我想知道是否有更好(或性能更高)的方法,例如dplyrdata.table

df_with_features <- plyr::join_all(list(count_x(df), sum_y(df), mean_y(df)),
                                   by = 'x', type = 'full')

# > df_with_features
#   x count_x sum_y mean_y
# 1 1       2   131   65.5
# 2 2       2   189   94.5
# 3 3       2   143   71.5
# 4 4       2   129   64.5
# 5 5       2   190   95.0

3
dplyr的格式是:df %>% group_by(x) %>% summarise(count_x = n(), sum_y = sum(y), mean_y = mean(y))。这一步操作即可完成所有列的处理。 - jeremycg
@jeremycg 当然,但是想象一下更复杂的函数,我不能把所有东西都传递到一个语句中。 - JasonAizkalns
2
@JasonAizkalns你能示范一下这个不起作用的地方吗? - Tyler Rinker
1
@TylerRinker @jeremycg 实际上,只需查看Jeremy的博客文章以获取示例(哈!我知道我从哪里无耻地窃取了这个概念/想法...这会教你晚上晚读Kaggle帖子的教训...)。我需要稍微修改我的示例,但他的博客文章指出了一些情况,其中一个对summarise的调用将无法工作(或者至少在维护方面更加困难的情况下)。 - JasonAizkalns
2
请看这里一个Reducemerge的例子:http://stackoverflow.com/a/33031393/2204410 - Jaap
显示剩余2条评论
2个回答

6

将@SimonOHanlon的data.table方法与@Jaap的Reducemerge技术相结合,似乎可以产生性能最佳的结果:

library(data.table)
setDT(df)
count_x_dt <- function(dt) dt[, list(count_x = .N), keyby = x]
sum_y_dt   <- function(dt) dt[, list(sum_y = sum(y)), keyby = x]
mean_y_dt  <- function(dt) dt[, list(mean_y = mean(y)), keyby = x]

Reduce(function(...) merge(..., all = TRUE, by = c("x")), 
       list(count_x_dt(df), sum_y_dt(df), mean_y_dt(df)))

更新内容包括使用 tidyverse / purrr (purrr::reduce) 方法:

library(tidyverse)
list(count_x(df), sum_y(df), mean_y(df)) %>% 
  reduce(left_join) 

2
在"data.table"术语中,这相当于拥有一个已排序键控的"data.table"并使用键来连接各种"data.tables"。
例如:
require(data.table)
setDT(df)  #df is now a data.table
df_count <- df[ , list(count_x=.N),by=x]
df_sum <- df[ , list(sum_y = sum(y)),by=x]
#  merge.data.table executes a fast join on the shared key
merge(df_count,df_sum)
#   x count_x sum_y
#1: 1       2   129
#2: 2       2   128
#3: 3       2   154
#4: 4       2   182
#5: 5       2   151

在您的例子中,您可以这样写:
count_x <- function(dt) dt[ , list(N = .N) , keyby=x ]
sum_y <- function(dt) dt[ , list(Sum=sum(y)),keyby=x]

#  Then merge...
merge(sum_y(df),count_x(df))
#   x Sum N
#1: 1 129 2
#2: 2 128 2
#3: 3 154 2
#4: 4 182 2
#5: 5 151 2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接