如何在 R 中同时合并多个 data.frames 和 sum 和 average 列
How to merge multiple data.frames and sum and average columns at the same time in R
我有 20 多个 data.frames 列相同但行数不同。我的目标是通过 "Name" 列(这是一个包含五个名称的列表)合并 data.frames 并且在合并时我希望具有相同名称的行对 A 列求和,对 B 列求和,并且得到 C 列的平均值。
这是我目前正在做的事情。
首先,我一次只合并 2 data.frames。
DF <- merge(x=abc, y=def, by = "Name", all = T)
合并后的DF会是这样
Name A.x B.x C.x A.y B.y C.y
name1,name2,name3,name4,name5 11 24 7 NA NA NA
name1,name3,name4,name6,name7 4 8 12 3 4 7
name1,name2,name5,name6,name7 12 4 5 NA NA NA
name3,name4,name5,name6,name7 NA NA NA 15 3 28
然后我将添加这些 ifelse
语句来处理 NAs
和非唯一行。对于非唯一行,它将为 A 添加 B,为 C 添加平均值。
DF$A <- ifelse(is.na(DF$A.x), DF$A.y,
ifelse(is.na(DF$A.y), DF$A.x,
ifelse((!is.na(DF$A.x)) & (!is.na(DF$A.y)), DF$A.x + DF$A.y, 1)))
DF$B <- ifelse(is.na(DF$B.x), DF$B.y,
ifelse(is.na(DF$B.y), DF$B.x,
ifelse((!is.na(DF$B.x)) & (!is.na(DF$B.y)), DF$B.x + DF$B.y, 1)))
DF$C <- ifelse(is.na(DF$C.x), DF$C.y,
ifelse(is.na(DF$C.y), DF$C.x,
ifelse((!is.na(DF$C.x)) & (!is.na(DF$C.y)), (DF$C.x + DF$C.y)/2, 1)))
DF 现在看起来像这样
Name A.x B.x C.x A.y B.y C.y A B C
name1,name2,name3,name4,name5 11 24 7 NA NA NA 11 24 7
name1,name3,name4,name6,name7 4 8 12 3 4 8 7 12 10
name1,name2,name5,name6,name7 12 4 5 NA NA NA 12 4 5
name3,name4,name5,name6,name7 NA NA NA 15 3 28 15 3 28
然后我只保留名称列和最后三列
merge1 <- DF[c(1,8,9,10)]
然后我对接下来的两个 data.frames 执行相同的过程并将其命名为 merge2。那我就合并merge1和merge 2.
total1 <- merge(x = merge1, y = merge2, by = "Name", all = TRUE)
我将继续一次合并两个数据帧,然后将总计 data.frames 一次合并两个。我得到了我想要的最终结果,但这是一个及时的过程而且效率不高。
我认为我可以做到的另一种方法是对所有 data.frames 进行 rbind,然后如果在名称列中的任何行与另一行具有相同的名称列表,则将其设为该行,添加 A 列,添加 B 列并获取 C 列的平均值。但我也不知道该怎么做。
这是我想要的外皮的例子
Name A B C
name1,name2,name3,name4,name5 11 24 7
name1,name3,name4,name6,name7 4 8 12
name1,name2,name5,name6,name7 12 4 5
name3,name4,name5,name6,name7 15 3 28
name1,name3,name4,name6,name7 3 4 8
最终结果会是这样
Name A B C
name1,name2,name3,name4,name5 11 24 7
name1,name3,name4,name6,name7 7 12 10
name1,name2,name5,name6,name7 12 4 5
name3,name4,name5,name6,name7 15 3 28
同样,我确信有比我目前正在做的更有效的方法来完成我想要的,所以任何帮助将不胜感激。
我认为您的第二种方法是可行的,您可以使用 data.table
或 dplyr
。
这里有几个步骤使用 data.table
。首先,如果你的数据框是 abc
, def
, ...
做:
DF <- do.call(rbind, list(abc,def,...))
现在您可以将它们转换成 data.table
DT <- data.table(DF)
然后简单地做类似
的事情
DTres <- DT[,.(A=sum(A, na.rm=T), B=sum(B, na.rm=T), C=mean(C,na.rm=T)),by=name]
仔细检查 data.table
小插图以更好地了解该程序包的工作原理。
我们可以使用dplyr
library(dplyr)
bind_rows(abc, def, ...) %>%
group_by(name) %>%
summarise(A= sum(A, na.rm= TRUE),
B = sum(B, na.rm= TRUE),
C = mean(C, na.rm=TRUE))
我有 20 多个 data.frames 列相同但行数不同。我的目标是通过 "Name" 列(这是一个包含五个名称的列表)合并 data.frames 并且在合并时我希望具有相同名称的行对 A 列求和,对 B 列求和,并且得到 C 列的平均值。
这是我目前正在做的事情。
首先,我一次只合并 2 data.frames。
DF <- merge(x=abc, y=def, by = "Name", all = T)
合并后的DF会是这样
Name A.x B.x C.x A.y B.y C.y
name1,name2,name3,name4,name5 11 24 7 NA NA NA
name1,name3,name4,name6,name7 4 8 12 3 4 7
name1,name2,name5,name6,name7 12 4 5 NA NA NA
name3,name4,name5,name6,name7 NA NA NA 15 3 28
然后我将添加这些 ifelse
语句来处理 NAs
和非唯一行。对于非唯一行,它将为 A 添加 B,为 C 添加平均值。
DF$A <- ifelse(is.na(DF$A.x), DF$A.y,
ifelse(is.na(DF$A.y), DF$A.x,
ifelse((!is.na(DF$A.x)) & (!is.na(DF$A.y)), DF$A.x + DF$A.y, 1)))
DF$B <- ifelse(is.na(DF$B.x), DF$B.y,
ifelse(is.na(DF$B.y), DF$B.x,
ifelse((!is.na(DF$B.x)) & (!is.na(DF$B.y)), DF$B.x + DF$B.y, 1)))
DF$C <- ifelse(is.na(DF$C.x), DF$C.y,
ifelse(is.na(DF$C.y), DF$C.x,
ifelse((!is.na(DF$C.x)) & (!is.na(DF$C.y)), (DF$C.x + DF$C.y)/2, 1)))
DF 现在看起来像这样
Name A.x B.x C.x A.y B.y C.y A B C
name1,name2,name3,name4,name5 11 24 7 NA NA NA 11 24 7
name1,name3,name4,name6,name7 4 8 12 3 4 8 7 12 10
name1,name2,name5,name6,name7 12 4 5 NA NA NA 12 4 5
name3,name4,name5,name6,name7 NA NA NA 15 3 28 15 3 28
然后我只保留名称列和最后三列
merge1 <- DF[c(1,8,9,10)]
然后我对接下来的两个 data.frames 执行相同的过程并将其命名为 merge2。那我就合并merge1和merge 2.
total1 <- merge(x = merge1, y = merge2, by = "Name", all = TRUE)
我将继续一次合并两个数据帧,然后将总计 data.frames 一次合并两个。我得到了我想要的最终结果,但这是一个及时的过程而且效率不高。
我认为我可以做到的另一种方法是对所有 data.frames 进行 rbind,然后如果在名称列中的任何行与另一行具有相同的名称列表,则将其设为该行,添加 A 列,添加 B 列并获取 C 列的平均值。但我也不知道该怎么做。
这是我想要的外皮的例子
Name A B C
name1,name2,name3,name4,name5 11 24 7
name1,name3,name4,name6,name7 4 8 12
name1,name2,name5,name6,name7 12 4 5
name3,name4,name5,name6,name7 15 3 28
name1,name3,name4,name6,name7 3 4 8
最终结果会是这样
Name A B C
name1,name2,name3,name4,name5 11 24 7
name1,name3,name4,name6,name7 7 12 10
name1,name2,name5,name6,name7 12 4 5
name3,name4,name5,name6,name7 15 3 28
同样,我确信有比我目前正在做的更有效的方法来完成我想要的,所以任何帮助将不胜感激。
我认为您的第二种方法是可行的,您可以使用 data.table
或 dplyr
。
这里有几个步骤使用 data.table
。首先,如果你的数据框是 abc
, def
, ...
做:
DF <- do.call(rbind, list(abc,def,...))
现在您可以将它们转换成 data.table
DT <- data.table(DF)
然后简单地做类似
的事情DTres <- DT[,.(A=sum(A, na.rm=T), B=sum(B, na.rm=T), C=mean(C,na.rm=T)),by=name]
仔细检查 data.table
小插图以更好地了解该程序包的工作原理。
我们可以使用dplyr
library(dplyr)
bind_rows(abc, def, ...) %>%
group_by(name) %>%
summarise(A= sum(A, na.rm= TRUE),
B = sum(B, na.rm= TRUE),
C = mean(C, na.rm=TRUE))