如何在列表中使用相同的列名 rbind 数据帧
how to rbind dataframes with identical column names in a list
我有一个这样的列表:
list=list(
df1=read.table(text = "a b c
11 14 20
17 15 12
6 19 17
",header=T),
df2=read.table(text = "a b c
6 19 12
9 7 19
",header=T),
df3=read.table(text = "a d f
12 20 15
12 10 8
7 8 7
",header=T),
df4=read.table(text = "g f e z
5 12 11 5
16 17 20 16
19 9 11 20
",header=T),
df5=read.table(text = "g f e z
15 13 9 18
12 12 17 16
15 9 12 11
15 20 19 15
",header=T),
df6=read.table(text = "a d f
11 7 16
11 12 11
",header=T)
)
我的列表包含不同的数据框。根据列名,列表中有 3 种类型的数据框。
type1:df1 and df2
type2:df3 and df6
type3:f4 and df5
我将 rbind
具有相同列名的数据帧并将结果保存在新列表中。例如,df1 和 df2、df3 和 df6 以及 df4 和 df5 具有相同的列 names.I 需要一个代码来自动识别和 rbind
具有相同列名的数据帧。
预期结果如下:
> new list
$df1.df2
a b c
1 11 14 20
2 17 15 12
3 6 19 17
4 6 19 12
5 9 7 19
$df3.df6
a d f
1 12 20 15
2 12 10 8
3 7 8 7
4 11 7 16
5 11 12 11
$df4.df5
g f e z
1 5 12 11 5
2 16 17 20 16
3 19 9 11 20
4 15 13 9 18
5 12 12 17 16
6 15 9 12 11
7 15 20 19 15
新列表中数据框的名称可以是任何名称。
因为我不喜欢命名变量 list
,所以我将您的数据命名为 l
。
lapply(
split(l, sapply(l, function(a) paste(colnames(a), collapse = "_"))),
dplyr::bind_rows)
# $a_b_c
# a b c
# 1 11 14 20
# 2 17 15 12
# 3 6 19 17
# 4 6 19 12
# 5 9 7 19
# $a_d_f
# a d f
# 1 12 20 15
# 2 12 10 8
# 3 7 8 7
# 4 11 7 16
# 5 11 12 11
# $g_f_e_z
# g f e z
# 1 5 12 11 5
# 2 16 17 20 16
# 3 19 9 11 20
# 4 15 13 9 18
# 5 12 12 17 16
# 6 15 9 12 11
# 7 15 20 19 15
我通常更喜欢使用 by(data, INDICES, FUN)
而不是 lapply(split(data, INDICES), FUN)
,但由于某种原因它一直在抱怨......所以上面。
选择将与 _
折叠的列名称连接在一起是任意的,目的是找到一个简单的 "hashing";不难设计出一种情况,即此方法发现两个相似的帧,而实际上它们不相似......也许不太可能引起关注。
我还应该注意,我使用的是 dplyr::bind_rows
,但没有使用 dplyr。这可以很容易地转换成使用 purrr::
或其他整洁包分组的东西。
我们可以
library(tidyverse)
library(janitor)
bind_rows(dfls) %>%
mutate(code= apply(apply(., 2, function(x){
ifelse(is.na(x), 1, 2)}), 1, paste, collapse="")) %>%
nest(.,-code, .key="code") %>%
mutate(filtered = map(code, janitor::remove_empty_cols)) %>%
pull(filtered) -> out
glimpse(out)
# List of 3
# $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 5 obs. of 3 variables:
# ..$ a: int [1:5] 11 17 6 6 9
# ..$ b: int [1:5] 14 15 19 19 7
# ..$ c: int [1:5] 20 12 17 12 19
# $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 5 obs. of 3 variables:
# ..$ a: int [1:5] 12 12 7 11 11
# ..$ d: int [1:5] 20 10 8 7 12
# ..$ f: int [1:5] 15 8 7 16 11
# $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 7 obs. of 4 variables:
# ..$ f: int [1:7] 12 17 9 13 12 9 20
# ..$ g: int [1:7] 5 16 19 15 12 15 15
# ..$ e: int [1:7] 11 20 11 9 17 12 19
# ..$ z: int [1:7] 5 16 20 18 16 11 15
我有一个这样的列表:
list=list(
df1=read.table(text = "a b c
11 14 20
17 15 12
6 19 17
",header=T),
df2=read.table(text = "a b c
6 19 12
9 7 19
",header=T),
df3=read.table(text = "a d f
12 20 15
12 10 8
7 8 7
",header=T),
df4=read.table(text = "g f e z
5 12 11 5
16 17 20 16
19 9 11 20
",header=T),
df5=read.table(text = "g f e z
15 13 9 18
12 12 17 16
15 9 12 11
15 20 19 15
",header=T),
df6=read.table(text = "a d f
11 7 16
11 12 11
",header=T)
)
我的列表包含不同的数据框。根据列名,列表中有 3 种类型的数据框。
type1:df1 and df2
type2:df3 and df6
type3:f4 and df5
我将 rbind
具有相同列名的数据帧并将结果保存在新列表中。例如,df1 和 df2、df3 和 df6 以及 df4 和 df5 具有相同的列 names.I 需要一个代码来自动识别和 rbind
具有相同列名的数据帧。
预期结果如下:
> new list
$df1.df2
a b c
1 11 14 20
2 17 15 12
3 6 19 17
4 6 19 12
5 9 7 19
$df3.df6
a d f
1 12 20 15
2 12 10 8
3 7 8 7
4 11 7 16
5 11 12 11
$df4.df5
g f e z
1 5 12 11 5
2 16 17 20 16
3 19 9 11 20
4 15 13 9 18
5 12 12 17 16
6 15 9 12 11
7 15 20 19 15
新列表中数据框的名称可以是任何名称。
因为我不喜欢命名变量 list
,所以我将您的数据命名为 l
。
lapply(
split(l, sapply(l, function(a) paste(colnames(a), collapse = "_"))),
dplyr::bind_rows)
# $a_b_c
# a b c
# 1 11 14 20
# 2 17 15 12
# 3 6 19 17
# 4 6 19 12
# 5 9 7 19
# $a_d_f
# a d f
# 1 12 20 15
# 2 12 10 8
# 3 7 8 7
# 4 11 7 16
# 5 11 12 11
# $g_f_e_z
# g f e z
# 1 5 12 11 5
# 2 16 17 20 16
# 3 19 9 11 20
# 4 15 13 9 18
# 5 12 12 17 16
# 6 15 9 12 11
# 7 15 20 19 15
我通常更喜欢使用 by(data, INDICES, FUN)
而不是 lapply(split(data, INDICES), FUN)
,但由于某种原因它一直在抱怨......所以上面。
选择将与 _
折叠的列名称连接在一起是任意的,目的是找到一个简单的 "hashing";不难设计出一种情况,即此方法发现两个相似的帧,而实际上它们不相似......也许不太可能引起关注。
我还应该注意,我使用的是 dplyr::bind_rows
,但没有使用 dplyr。这可以很容易地转换成使用 purrr::
或其他整洁包分组的东西。
我们可以
library(tidyverse)
library(janitor)
bind_rows(dfls) %>%
mutate(code= apply(apply(., 2, function(x){
ifelse(is.na(x), 1, 2)}), 1, paste, collapse="")) %>%
nest(.,-code, .key="code") %>%
mutate(filtered = map(code, janitor::remove_empty_cols)) %>%
pull(filtered) -> out
glimpse(out)
# List of 3
# $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 5 obs. of 3 variables:
# ..$ a: int [1:5] 11 17 6 6 9
# ..$ b: int [1:5] 14 15 19 19 7
# ..$ c: int [1:5] 20 12 17 12 19
# $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 5 obs. of 3 variables:
# ..$ a: int [1:5] 12 12 7 11 11
# ..$ d: int [1:5] 20 10 8 7 12
# ..$ f: int [1:5] 15 8 7 16 11
# $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 7 obs. of 4 variables:
# ..$ f: int [1:7] 12 17 9 13 12 9 20
# ..$ g: int [1:7] 5 16 19 15 12 15 15
# ..$ e: int [1:7] 11 20 11 9 17 12 19
# ..$ z: int [1:7] 5 16 20 18 16 11 15