#r #bind
#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
Комментарии:
1. В вашем вопросе вы говорите «объединить», «связать» и » » — все это звучит как разные операции. Не могли бы вы показать ожидаемый результат для
DF1
?2. И когда вы говорите «Сохранить имя», вы имеете в виду, что вам нужно иметь возможность определить, из какого фрейма данных получено каждое наблюдение в результате? Или просто вам нужно знать, какие два фрейма данных являются частью данного результирующего фрейма данных?
3. Я отредактировал вопрос, чтобы придать ему больше смысла
4. Кроме того, может быть полезно знать вашу версию R или, по крайней мере, класс столбцов. В R версии 4.0 R переключился со старого значения по умолчанию, которое
first_column
будетfactor
class, на новое значение по умолчанию, которое будетcharacter
class .5. У вас есть еще суффиксы или
"A"
и"B"
являются единственными?
Ответ №1:
Вы имеете в виду что-то вроде этого?
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
Комментарии:
1. Я думаю, что первый из них lapply (split (mylist, gsub(«_.*», «», имена(mylist))), функция(v)
row.names<-
((out <- do.call(rbind, v))[do.call(order, out), ], NULL) ) лучше, просто потому, что он дает вам имена строк, указывающие, откуда взялась эта переменная!2. @GabrielG. Спасибо. Я думаю, что заголовок вашего вопроса должен быть
stack
илиrow bind
, а неmerge
. Лучше сделать более понятный заголовок для других читателей.3. Могу ли я выбрать количество столбцов для rbind, если у df их разное количество? например, [,1:3]?
4. @GabrielG. Да, вы можете, но вы должны убедиться, что выбранные вами столбцы имеют одинаковые имена столбцов (поскольку
rbind
это требуется). Лучше выбирать столбцы по их именам, а не по индексам.
Ответ №2:
Вот решение с Map
, но оно работает только для двух суффиксов. Если вы хотите merge
, используйте первую Map
инструкцию; если вы хотите сохранить дубликаты, используйте 2- 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))
Ответ №3:
Одним из многих обязательных 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)
Также для подобных вещей bind_rows()
from dplyr
имеет .id
аргумент, который добавит столбец с именем элемента списка и сложит строки. Это также может быть полезным способом. Вы можете привязать, изменить имя, как хотите, а затем split()
.