两个两个(或按名称)绑定列表中的数据帧 - R
Bind dataframes in a list two by two (or by name) - R
假设我有这个数据帧列表:
DF1_A<- data.frame (first_column = c("A", "B","C"),
second_column = c(5, 5, 5),
third_column = c(1, 1, 1)
)
DF1_B <- data.frame (first_column = c("A", "B","E"),
second_column = c(1, 1, 5),
third_column = c(1, 1, 1)
)
DF2_A <- data.frame (first_column = c("E", "F","G"),
second_column = c(1, 1, 5),
third_column = c(1, 1, 1)
)
DF2_B <- data.frame (first_column = c("K", "L","B"),
second_column = c(1, 1, 5),
third_column = c(1, 1, 1)
)
mylist <- list(DF1_A, DF1_B, DF2_A, DF2_B)
names(mylist) = c("DF1_A", "DF1_B", "DF2_A", "DF2_B")
mylist = lapply(mylist, function(x){
x[, "first_column"] <- as.character(x[, "first_column"])
x
})
我想通过名称(所有 DF1、所有 DF2 等)绑定它们,或者客观地,在此有序命名列表中两个两个绑定。保持列表的“命名列表结构”对于跟踪很重要(例如,DF1_A 和 DF1_B = DF1 或名称(mylist)中的类似内容)
有些行有重复的值,我想保留它们(这会引入一些重复的字符,例如first_column,值A)
我曾尝试在此处找到有关堆栈溢出的任何线索,但大多数人都希望绑定数据帧,而不考虑其名称或顺序。
最终结果如下所示:
mylist
DF1
DF2
DF1
first_column second_column third_column
A 1 1
A 5 1
B 1 1
B 5 1
C 5 1
E 5 1
这里有一个 Map
的解决方案,但它只适用于两个后缀。如果要merge
,使用第一个Map
指令;如果您想保留重复项,请使用第二个 rbind
解决方案。
sp <- split(mylist, sub("^DF.*_", "", names(mylist)))
res1 <- Map(function(x, y)merge(x, y, all = TRUE), sp[["A"]], sp[["B"]])
res2 <- Map(function(x, y)rbind(x, y), sp[["A"]], sp[["B"]])
names(res1) <- sub("_.*$", "", names(res1))
names(res2) <- sub("_.*$", "", names(res2))
你的意思是这样的吗?
lapply(
split(mylist, gsub("_.*", "", names(mylist))),
function(v) `row.names<-`((out <- do.call(rbind, v))[do.call(order, out), ], NULL)
)
这给出了
$DF1
first_column second_column third_column
1 A 1 1
2 A 5 1
3 B 1 1
4 B 5 1
5 C 5 1
6 E 5 1
$DF2
first_column second_column third_column
1 B 5 1
2 E 1 1
3 F 1 1
4 G 5 1
5 K 1 1
6 L 1 1
许多强制性 tidyverse
解决方案之一可以是这个。
library(purrr)
library(stringr)
# find the unique DF names
unique_df <- set_names(unique(str_split_fixed(names(mylist), "_", 2)[,1]))
# loop over each unique name, extracting the elements and binding into columns
purrr::map(unique_df, ~ keep(mylist, str_starts(names(mylist), .x))) %>%
map(bind_rows)
同样对于这样的事情,dplyr
中的 bind_rows()
有一个 .id
参数,它将添加一个带有列表元素名称的列,并堆叠行。这也是一种有用的方法。您可以绑定,随意操作名称,然后 split()
.
假设我有这个数据帧列表:
DF1_A<- data.frame (first_column = c("A", "B","C"),
second_column = c(5, 5, 5),
third_column = c(1, 1, 1)
)
DF1_B <- data.frame (first_column = c("A", "B","E"),
second_column = c(1, 1, 5),
third_column = c(1, 1, 1)
)
DF2_A <- data.frame (first_column = c("E", "F","G"),
second_column = c(1, 1, 5),
third_column = c(1, 1, 1)
)
DF2_B <- data.frame (first_column = c("K", "L","B"),
second_column = c(1, 1, 5),
third_column = c(1, 1, 1)
)
mylist <- list(DF1_A, DF1_B, DF2_A, DF2_B)
names(mylist) = c("DF1_A", "DF1_B", "DF2_A", "DF2_B")
mylist = lapply(mylist, function(x){
x[, "first_column"] <- as.character(x[, "first_column"])
x
})
我想通过名称(所有 DF1、所有 DF2 等)绑定它们,或者客观地,在此有序命名列表中两个两个绑定。保持列表的“命名列表结构”对于跟踪很重要(例如,DF1_A 和 DF1_B = DF1 或名称(mylist)中的类似内容)
有些行有重复的值,我想保留它们(这会引入一些重复的字符,例如first_column,值A)
我曾尝试在此处找到有关堆栈溢出的任何线索,但大多数人都希望绑定数据帧,而不考虑其名称或顺序。
最终结果如下所示:
mylist
DF1
DF2
DF1
first_column second_column third_column
A 1 1
A 5 1
B 1 1
B 5 1
C 5 1
E 5 1
这里有一个 Map
的解决方案,但它只适用于两个后缀。如果要merge
,使用第一个Map
指令;如果您想保留重复项,请使用第二个 rbind
解决方案。
sp <- split(mylist, sub("^DF.*_", "", names(mylist)))
res1 <- Map(function(x, y)merge(x, y, all = TRUE), sp[["A"]], sp[["B"]])
res2 <- Map(function(x, y)rbind(x, y), sp[["A"]], sp[["B"]])
names(res1) <- sub("_.*$", "", names(res1))
names(res2) <- sub("_.*$", "", names(res2))
你的意思是这样的吗?
lapply(
split(mylist, gsub("_.*", "", names(mylist))),
function(v) `row.names<-`((out <- do.call(rbind, v))[do.call(order, out), ], NULL)
)
这给出了
$DF1
first_column second_column third_column
1 A 1 1
2 A 5 1
3 B 1 1
4 B 5 1
5 C 5 1
6 E 5 1
$DF2
first_column second_column third_column
1 B 5 1
2 E 1 1
3 F 1 1
4 G 5 1
5 K 1 1
6 L 1 1
许多强制性 tidyverse
解决方案之一可以是这个。
library(purrr)
library(stringr)
# find the unique DF names
unique_df <- set_names(unique(str_split_fixed(names(mylist), "_", 2)[,1]))
# loop over each unique name, extracting the elements and binding into columns
purrr::map(unique_df, ~ keep(mylist, str_starts(names(mylist), .x))) %>%
map(bind_rows)
同样对于这样的事情,dplyr
中的 bind_rows()
有一个 .id
参数,它将添加一个带有列表元素名称的列,并堆叠行。这也是一种有用的方法。您可以绑定,随意操作名称,然后 split()
.