У меня есть такой список:
df_list <- list(
df1 = data.frame(A = 1:3, B = 4:6),
df2 = data.frame(A = 7:9, B = 10:12),
df3 = data.frame(A = 13:15, C = 16:18),
df4 = data.frame(A = 19:21, B = 22:24, C = 25:27)
)
Для всех фреймов данных в этом списке, которые имеют одинаковое количество столбцов И одинаковые имена столбцов, я хочу поместить их в отдельный список (например, list_1, list_2, list_3...).
Кто-нибудь знает, есть ли быстрый способ сделать это?
Обновлено: Вот ответ @ Эдварда в более старой версии R:
split_list <- function() {
unique_names <- unique(lapply(my_list, names))
res <- lapply(unique_names, function(x) {
lapply(my_list, function(y) {
if (identical(names(y), x)) y else NULL
})
})
for(i in seq_along(res)) {
current_list <- res[[i]]
non_empty_list <- Filter(function(x) !is.null(x) && ncol(x) > 0, current_list)
assign(paste("list", i, sep = "_"), non_empty_list, envir = .GlobalEnv)
}
}
split_list()
#clean up
all_objects <- ls()
for (obj in all_objects) {
if (is.list(get(obj)) && (length(get(obj)) == 0 || length(get(obj)) == 1)) {
rm(list = obj)
}
}
Каков ваш желаемый результат для этих игрушечных данных?
@ Рик: Думаю, именно так можно написать это в старой версии R? Split(df_list, sapply(df_list, function(x) Paste(sort(make.names(names(x))), коллапс = " ")))
Создайте функцию для этого.
split_list <- function(lst) {
res <- lapply(unique(lapply(lst, names)), \(x) {
lapply(lst, \(y) y[identical(names(y), x)]) })
for(i in 1:length(res)) {
assign(paste("list", i, sep = "_"), res[[i]]
[sapply(res[[i]], \(x) ncol(x)>0)])
}
}
Затем вызовите эту функцию, чтобы создать отдельные списки в среде.
split_list(df_list)
list_1
$df1
A B
1 1 4
2 2 5
3 3 6
$df2
A B
1 7 10
2 8 11
3 9 12
list_2
$df3
A C
1 13 16
2 14 17
3 15 18
list_3
$df4
A B C
1 19 22 25
2 20 23 26
3 21 24 27
@ Эдвард: Я думаю, именно так бы вы и поступили в старой версии R?
Split_list <- function(lst) { unique_names <- unique(lapply(lst, name)) res <- lapply(unique_names, function(x) { lapply(lst, function(y) { if (identical(names(y), х)) y еще NULL }) })
for(i in seq_along(res)) { current_list <- res[[i]] non_empty_list <- Filter(function(x) !is.null(x) && ncol(x) > 0, current_list) Assign(paste(" list", i, sep = "_"), non_empty_list, envir = .GlobalEnv) } }
split(df_list, sapply(df_list, \(x) paste(sort(make.names(names(x))), collapse = " ")))