Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 对匹配行的数据帧进行递归求和_R_Dplyr_Plyr - Fatal编程技术网

R 对匹配行的数据帧进行递归求和

R 对匹配行的数据帧进行递归求和,r,dplyr,plyr,R,Dplyr,Plyr,我希望通过对具有匹配变量的列求和,而不是追加列,将一组数据帧组合成单个数据帧 例如,给定 df1 <- data.frame(A = c(0,0,1,1,1,2,2), B = c(1,2,1,2,3,1,5), x = c(2,3,1,5,3,7,0)) df2 <- data.frame(A = c(0,1,1,2,2,2), B = c(1,1,3,2,4,5), x = c(4,8,4,1,0,3)) df3 <- data.frame(A = c(0,1,2), B

我希望通过对具有匹配变量的列求和,而不是追加列,将一组数据帧组合成单个数据帧

例如,给定

df1 <- data.frame(A = c(0,0,1,1,1,2,2), B = c(1,2,1,2,3,1,5), x = c(2,3,1,5,3,7,0))
df2 <- data.frame(A = c(0,1,1,2,2,2), B = c(1,1,3,2,4,5), x = c(4,8,4,1,0,3))
df3 <- data.frame(A = c(0,1,2), B = c(5,4,2), x = c(5,3,1))
结果:

       A     B     x
   <dbl> <dbl> <dbl>
 1     0     1     6
 2     0     2     3
 3     0     5     5
 4     1     1     9
 5     1     2     5
 6     1     3     7
 7     1     4     3
 8     2     1     7
 9     2     2     2
10     2     4     0
11     2     5     3
一个更普遍的解决方案是

library(dplyr)
# function to get the desired result for two data frames:
my_merge <- function(df1, df2)
{
  m1 <- merge(df1, df2, by = c("A", "B"), all = TRUE)
  m1 <- rowwise(res) %>% 
    mutate(x = sum(x.x, x.y, na.rm = TRUE)) %>%
    select(A, B, x)
  return(m1)
}
l1 <- list(df2, df3) # omit the first data frame
res <- df1 # initial value of the result
for(df in l1) res <- my_merge(res, df) # call the function repeatedly

是否有更有效的方法来组合大量数据帧?理想情况下,它应该是递归的,即在计算总和之前,最好不要将所有数据帧合并到一个海量数据帧中。

一个更简单的选择是绑定数据集的行,然后按感兴趣的列分组,并通过获得“x”的总和来获得汇总输出

正如OP提到的内存约束,如果我们先进行连接,然后使用行和或+加上reduce,那么效率会更高

mget(ls(pattern= "^df\\d+")) %>% 
      reduce(full_join, by = c("A", "B")) %>%
      transmute(A, B, x = rowSums(.[3:5], na.rm = TRUE)) %>%
      arrange(A, B)
#   A B x
#1  0 1 6
#2  0 2 3
#3  0 5 5
#4  1 1 9
#5  1 2 5
#6  1 3 7
#7  1 4 3
#8  2 1 7
#9  2 2 2
#10 2 4 0
#11 2 5 3
这也可以通过data.table完成


一个更简单的选择是绑定数据集的行,然后按感兴趣的列分组,并通过获得“x”的总和来获得汇总输出

正如OP提到的内存约束,如果我们先进行连接,然后使用行和或+加上reduce,那么效率会更高

mget(ls(pattern= "^df\\d+")) %>% 
      reduce(full_join, by = c("A", "B")) %>%
      transmute(A, B, x = rowSums(.[3:5], na.rm = TRUE)) %>%
      arrange(A, B)
#   A B x
#1  0 1 6
#2  0 2 3
#3  0 5 5
#4  1 1 9
#5  1 2 5
#6  1 3 7
#7  1 4 3
#8  2 1 7
#9  2 2 2
#10 2 4 0
#11 2 5 3
这也可以通过data.table完成

理想情况下,它应该是递归的,也就是说,在计算和之前,最好不要将所有数据帧合并到一个海量数据帧中

如果您的内存有限,并且愿意牺牲速度而不是@akrun的data.table方法,请在循环中一次使用一个表:

library(data.table)
tabs = c("df1", "df2", "df3")

# enumerate all combos for the results table
# initializing sum to 0
res = CJ(A = 0:2, B = 1:5, x = 0)
# loop over tabs, adding on
for (i in seq_along(tabs)){
  tab = get(tabs[[i]])
  res[tab, on=.(A, B), x := x + i.x][]
  rm(tab)
}
如果您需要从磁盘读取表,请将选项卡更改为文件名,然后转到fread或任何函数

我怀疑你是否能把所有的表都放在内存中,但也不能把它们的一个rbind-ed副本放在一起

同样感谢@akrun的评论,两两使用他的方法:

res = data.table(get(tabs[[1]]))[0L]

for (i in seq_along(tabs)){
  tab = get(tabs[[i]])
  res = rbind(res, tab)[, .(x = sum(x)), by=.(A,B)]
  rm(tab)
}
理想情况下,它应该是递归的,也就是说,在计算和之前,最好不要将所有数据帧合并到一个海量数据帧中

如果您的内存有限,并且愿意牺牲速度而不是@akrun的data.table方法,请在循环中一次使用一个表:

library(data.table)
tabs = c("df1", "df2", "df3")

# enumerate all combos for the results table
# initializing sum to 0
res = CJ(A = 0:2, B = 1:5, x = 0)
# loop over tabs, adding on
for (i in seq_along(tabs)){
  tab = get(tabs[[i]])
  res[tab, on=.(A, B), x := x + i.x][]
  rm(tab)
}
如果您需要从磁盘读取表,请将选项卡更改为文件名,然后转到fread或任何函数

我怀疑你是否能把所有的表都放在内存中,但也不能把它们的一个rbind-ed副本放在一起

同样感谢@akrun的评论,两两使用他的方法:

res = data.table(get(tabs[[1]]))[0L]

for (i in seq_along(tabs)){
  tab = get(tabs[[i]])
  res = rbind(res, tab)[, .(x = sum(x)), by=.(A,B)]
  rm(tab)
}

谢谢我考虑过绑定行,但这不会导致在内存中暂时保存一个潜在的巨大组合数据帧吗?@rob我考虑的是效率问题。我想很难避免在速度和内存使用之间进行权衡。谢谢!我考虑过绑定行,但这不会导致在内存中暂时保存一个潜在的巨大组合数据帧吗?@rob我考虑的是效率问题。我想很难避免在速度和内存使用之间进行折衷。如果你说合并或完全联接更高效,那没关系,但我认为行方式和以后的求和方式效率会很低。我会使用行和或减少+这很好,谢谢!因此,我可以用res%mutatex=rowSumsselect.,x.x,x.y,na.rm=TRUE%>%selectA,B,x替换我的合并中的第二行。如果你说合并或完全连接更节省内存,这是可以的,但我认为行和后面的总和将是低效的。我会使用行和或减少+这很好,谢谢!所以我可以用res%mutatex=rowSumsselect.,x.x,x.y,na.rm=TRUE%>%selectA,B,x替换我合并中的第二行。谢谢!事实上,我从一个单独的文件中读取每个数据帧,因此循环选项很诱人。很高兴您和@akrun提供了各种选项来测试最佳内存/速度。@rob Cool:如果您有其他方法,请通过另一个答案告诉我们。我不习惯关注RAM,所以我真的不知道最好的方法。谢谢!事实上,我从一个单独的文件中读取每个数据帧,因此循环选项很诱人。很高兴您和@akrun提供了各种选项来测试最佳内存/速度。@rob Cool:如果您有其他方法,请通过另一个答案告诉我们。我不习惯于关注RAM,所以不知道最好的方法。
res = data.table(get(tabs[[1]]))[0L]

for (i in seq_along(tabs)){
  tab = get(tabs[[i]])
  res = rbind(res, tab)[, .(x = sum(x)), by=.(A,B)]
  rm(tab)
}