如何合并和聚合 3 个以上不同长度和名称的数据帧
how to merge AND aggregate 3+ data frames of different lengths and colnames
我有三个结构相似但列名和行数不同的数据框。
> a
ID count alpha
1 207 1 1
2 351 1 1
3 372 1 1
4 595 4 1
5 596 1 1
6 652 1 1
> b
ID count beta
1 207 1 1
2 351 1 1
3 372 1 1
4 1024 6 1
> c
ID count zeta
1 207 4 1
2 351 1 1
3 372 1 1
4 595 2 1
我需要创建一个新的数据框,其中包含来自两者(id、count、alpha、beta)的所有列,同时输出计数的总和。如果一个 ID 只出现在一个数据框中,它应该在相应的列中输出 0。期望的输出如下:
> abc
ID count alpha beta zeta
1 207 6 1 1 1
2 351 3 1 1 1
3 372 3 1 1 1
4 595 6 1 0 1
5 596 1 1 0 0
6 652 1 1 0 0
7 1024 6 0 1 0
我在 a 和 b 上尝试了 merge() 并得到了这个输出:
> merge(a, b, by=intersect(names(a),names(b)), all=TRUE, sort=TRUE)
id count alpha beta
1 207 1 1 1
2 351 1 1 1
3 372 1 1 1
4 595 4 1 NA
5 596 1 1 NA
6 652 1 1 NA
7 1024 6 NA 1
我同意 0 是 NA,但我对这个输出有两个主要问题:
(1) 计数列不求和
(2) merge() 仅适用于 2 个数据框,实际上我有更多(例如 10 个)
欢迎任何建议。
以下是我的处理方法:
- 创建相关
data.frame
的 list
(就像将它们全部放入 list()
一样简单。
- 使用
rbindlist
(或其他增强的 rbind
函数之一,它允许您按行将数据集绑定在一起 即使列不同 --请参阅 "plyr" 和 "dplyr" 了解 rbindlist
的其他常见替代方法)。
在这里,我使用了 "data.table" 中的 rbindlist
。
library(data.table)
rbindlist(list(a, b, c), use.names = TRUE, fill = TRUE)[
, lapply(.SD, sum, na.rm = TRUE), by = ID]
# ID count alpha beta zeta
# 1: 207 6 1 1 1
# 2: 351 3 1 1 1
# 3: 372 3 1 1 1
# 4: 595 6 1 0 1
# 5: 596 1 1 0 0
# 6: 652 1 1 0 0
# 7: 1024 6 0 1 0
我不确定这是否正是您想要处理 "alpha"、"beta"、... 列的方式。我刚刚总结了一切。
此答案中使用的示例数据:
a <- structure(list(
ID = c(207L, 351L, 372L, 595L, 596L, 652L),
count = c(1L, 1L, 1L, 4L, 1L, 1L),
alpha = c(1L, 1L, 1L, 1L, 1L, 1L)),
.Names = c("ID", "count", "alpha"),
class = "data.frame",
row.names = c("1", "2", "3", "4", "5", "6"))
b <- structure(list(
ID = c(207L, 351L, 372L, 1024L),
count = c(1L, 1L, 1L, 6L), beta = c(1L, 1L, 1L, 1L)),
.Names = c("ID", "count", "beta"),
class = "data.frame", row.names = c("1", "2", "3", "4"))
c <- structure(list(
ID = c(207L, 351L, 372L, 595L),
count = c(4L, 1L, 1L, 2L), zeta = c(1L, 1L, 1L, 1L)),
.Names = c("ID", "count", "zeta"),
class = "data.frame", row.names = c("1", "2", "3", "4"))
这可以通过 dplyr
分阶段完成。
给出的数据:
dfA <- data.frame(c(207, 351, 372, 595, 596, 652), c(1, 1, 1, 4, 1, 1), rep(1, 6))
names(dfA) <- c('ID', 'count', 'alpha')
dfB <- data.frame(c(207, 351, 372, 1024), c(1, 1, 1, 6), rep(1, 4))
names(dfB) <- c('ID', 'count', 'beta')
dfC <- data.frame(c(207, 351, 372, 595), c(4, 1, 1, 2), rep(1, 4))
names(dfC) <- c('ID', 'count', 'zeta')
以下虽然有点难看,但可以工作:
library(dplyr)
dfT <- bind_rows(dfA, dfB, dfC)
df_1 <- dfT %>% group_by(ID) %>% summarise(sum(count))
df_F <- data.frame(df_1, as.numeric(df_i$ID %in% dfA$ID), as.numeric(df_i$ID %in% dfB$ID), as.numeric(df_i$ID %in% dfC$ID))
names(df_F) <- c("ID", "count", "alpha", "beta", "zeta")
> df_F
ID count alpha beta zeta
1 207 6 1 1 1
2 351 3 1 1 1
3 372 3 1 1 1
4 595 6 1 0 1
5 596 1 1 0 0
6 652 1 1 0 0
7 1024 6 0 1 0
我有三个结构相似但列名和行数不同的数据框。
> a
ID count alpha
1 207 1 1
2 351 1 1
3 372 1 1
4 595 4 1
5 596 1 1
6 652 1 1
> b
ID count beta
1 207 1 1
2 351 1 1
3 372 1 1
4 1024 6 1
> c
ID count zeta
1 207 4 1
2 351 1 1
3 372 1 1
4 595 2 1
我需要创建一个新的数据框,其中包含来自两者(id、count、alpha、beta)的所有列,同时输出计数的总和。如果一个 ID 只出现在一个数据框中,它应该在相应的列中输出 0。期望的输出如下:
> abc
ID count alpha beta zeta
1 207 6 1 1 1
2 351 3 1 1 1
3 372 3 1 1 1
4 595 6 1 0 1
5 596 1 1 0 0
6 652 1 1 0 0
7 1024 6 0 1 0
我在 a 和 b 上尝试了 merge() 并得到了这个输出:
> merge(a, b, by=intersect(names(a),names(b)), all=TRUE, sort=TRUE)
id count alpha beta
1 207 1 1 1
2 351 1 1 1
3 372 1 1 1
4 595 4 1 NA
5 596 1 1 NA
6 652 1 1 NA
7 1024 6 NA 1
我同意 0 是 NA,但我对这个输出有两个主要问题:
(1) 计数列不求和
(2) merge() 仅适用于 2 个数据框,实际上我有更多(例如 10 个)
欢迎任何建议。
以下是我的处理方法:
- 创建相关
data.frame
的list
(就像将它们全部放入list()
一样简单。 - 使用
rbindlist
(或其他增强的rbind
函数之一,它允许您按行将数据集绑定在一起 即使列不同 --请参阅 "plyr" 和 "dplyr" 了解rbindlist
的其他常见替代方法)。
在这里,我使用了 "data.table" 中的 rbindlist
。
library(data.table)
rbindlist(list(a, b, c), use.names = TRUE, fill = TRUE)[
, lapply(.SD, sum, na.rm = TRUE), by = ID]
# ID count alpha beta zeta
# 1: 207 6 1 1 1
# 2: 351 3 1 1 1
# 3: 372 3 1 1 1
# 4: 595 6 1 0 1
# 5: 596 1 1 0 0
# 6: 652 1 1 0 0
# 7: 1024 6 0 1 0
我不确定这是否正是您想要处理 "alpha"、"beta"、... 列的方式。我刚刚总结了一切。
此答案中使用的示例数据:
a <- structure(list(
ID = c(207L, 351L, 372L, 595L, 596L, 652L),
count = c(1L, 1L, 1L, 4L, 1L, 1L),
alpha = c(1L, 1L, 1L, 1L, 1L, 1L)),
.Names = c("ID", "count", "alpha"),
class = "data.frame",
row.names = c("1", "2", "3", "4", "5", "6"))
b <- structure(list(
ID = c(207L, 351L, 372L, 1024L),
count = c(1L, 1L, 1L, 6L), beta = c(1L, 1L, 1L, 1L)),
.Names = c("ID", "count", "beta"),
class = "data.frame", row.names = c("1", "2", "3", "4"))
c <- structure(list(
ID = c(207L, 351L, 372L, 595L),
count = c(4L, 1L, 1L, 2L), zeta = c(1L, 1L, 1L, 1L)),
.Names = c("ID", "count", "zeta"),
class = "data.frame", row.names = c("1", "2", "3", "4"))
这可以通过 dplyr
分阶段完成。
给出的数据:
dfA <- data.frame(c(207, 351, 372, 595, 596, 652), c(1, 1, 1, 4, 1, 1), rep(1, 6))
names(dfA) <- c('ID', 'count', 'alpha')
dfB <- data.frame(c(207, 351, 372, 1024), c(1, 1, 1, 6), rep(1, 4))
names(dfB) <- c('ID', 'count', 'beta')
dfC <- data.frame(c(207, 351, 372, 595), c(4, 1, 1, 2), rep(1, 4))
names(dfC) <- c('ID', 'count', 'zeta')
以下虽然有点难看,但可以工作:
library(dplyr)
dfT <- bind_rows(dfA, dfB, dfC)
df_1 <- dfT %>% group_by(ID) %>% summarise(sum(count))
df_F <- data.frame(df_1, as.numeric(df_i$ID %in% dfA$ID), as.numeric(df_i$ID %in% dfB$ID), as.numeric(df_i$ID %in% dfC$ID))
names(df_F) <- c("ID", "count", "alpha", "beta", "zeta")
> df_F
ID count alpha beta zeta
1 207 6 1 1 1
2 351 3 1 1 1
3 372 3 1 1 1
4 595 6 1 0 1
5 596 1 1 0 0
6 652 1 1 0 0
7 1024 6 0 1 0