首页 > 解决方案 > 在 data.table 和/或 dplyr 中跨组和列应用函数

问题描述

我想组合两个不等行的data.tables或dataframes,其中dt2的行数与dt1的组数相同。这是一个可重现的示例:

a <- 1:10; b <- 2:11; c <- 3:12
groupVar <- c(1,1,1,2,2,2,3,3,3,3)
dt1 <- data.table(a,b,c,groupVar)
a2 <- c(10,20,30); b2 <- c(20,30,40); c2 <- c(30,40,50)
dt2 <- data.table(a2,b2,c2)

实际情况涉及大量列,因此我使用变量来引用它们。使用循环或应用,我希望将 dt2 的每一行添加到组成每组 dt1 的行中。这是失败的众多尝试之一:

for (ic in 1:3) {
  c1 <- dt2[,(ic), with=FALSE]
  c2 <- dt2[,(ic), with=FALSE]
  dt1[,(ic) := .(c1 + c2[.G]), by = "groupVar"]
}

我对如何在 data.table 语法和 dplyr 语法中“按组和按列”执行这种操作很感兴趣。到位(如上所述)并不重要。

期望的结果:

dt1 (or dt3) = 
a   b   c   groupVar
11  22  33  1
12  23  34  1
13  24  35  1
24  35  46  2 
...
40  51  62  3

标签: rdplyrdata.table

解决方案


假设列名是一致的(例如,您想要 a + a2、b + b2...等),这里有一个 tidyverse 解决方案,它以与@dclarson 类似的方式开始,然后使用 bang-bang 运算符选择列加起来。

这就是你所追求的吗?

## Create tibbles and join
dt1 <- tibble(groupVar,a,b,c)
dt2 <- tibble(groupVar = 1:3,a2,b2,c2)
dt3 <- inner_join(dt1,dt2)

## Define the column starters you are interested in
cols <- c("a","b","c")
## Or in case of many columns
cols <- colnames(dt1[-1])

## Create function to add columns with the same starting letters
add_cols <- function(col){
  dt3 %>% select(starts_with(!!col)) %>% 
    transmute(!!(sym(col)) :=  !!(sym(col)) +  !!(sym(paste0(col,"2")))) 
}
## map the function and add groupVar
 map_dfc(cols,add_cols) %>% mutate(groupVar = dt3$groupVar)

    # A tibble: 10 x 4
       a     b     c groupVar
   <dbl> <dbl> <dbl>    <dbl>
 1    11    22    33        1
 2    12    23    34        1
 3    13    24    35        1
 4    24    35    46        2
 5    25    36    47        2
 6    26    37    48        2
 7    37    48    59        3
 8    38    49    60        3
 9    39    50    61        3
10    40    51    62        3

推荐阅读