rbind два data.frame с сохранением порядка строк и имен строк

У меня есть список объектов data.frame, которые я хотел бы добавить друг к другу, т.е. merge(..., all=T). Однако merge, похоже, удаляет имена строк, которые мне нужно сохранить. Любые идеи? Пример:

x = data.frame(a=1:2, b=2:3, c=3:4, d=4:5, row.names=c("row_1", "another_row1"))
y = data.frame(a=c(10,20), b=c(20,30), c=c(30,40), row.names=c("row_2", "another_row2"))
> merge(x, y, all=T, sort=F)
     a  b  c  d
  1  1  2  3  4
  2  2  3  4  5
  3 10 20 30 NA
  4 20 30 40 NA

person Alex    schedule 10.02.2013    source источник
comment
может быть z ‹- слияние (x, y, all=T, sort=F); имена строк (z) ‹- c (имена строк (x), имена строк (y))   -  person Arnaud A    schedule 10.02.2013
comment
Если я вас правильно понял, вы хотите rbind фреймы данных с разным количеством столбцов вместе. Этот вопрос может быть вам полезен, в частности, rbind.fill из пакета plyr.   -  person Blue Magister    schedule 10.02.2013
comment
@Arun ответ Ананды Махто позаботится об этом.   -  person Blue Magister    schedule 10.02.2013


Ответы (2)


Поскольку вы знаете, что на самом деле вы не объединяете, а просто объединяете, возможно, что-то вроде этого сработает. Он использует rbind.fill от «plyr». Чтобы использовать его, укажите list из data.frame, которые вы хотите rbind.

RBIND <- function(datalist) {
  require(plyr)
  temp <- rbind.fill(datalist)
  rownames(temp) <- unlist(lapply(datalist, row.names))
  temp
}
RBIND(list(x, y))
#               a  b  c  d
# row_1         1  2  3  4
# another_row1  2  3  4  5
# row_2        10 20 30 NA
# another_row2 20 30 40 NA
person A5C1D2H2I1M1N2O1R2T1    schedule 10.02.2013

Один из способов — использовать row.names в слиянии, чтобы получить его как дополнительный столбец.

> merge(x, y, by=c("row.names", "a","b","c"), all.x=T, all.y=T, sort=F)

#      Row.names  a  b  c  d
# 1        row_1  1  2  3  4
# 2 another_row1  2  3  4  5
# 3        row_2 10 20 30 NA
# 4 another_row2 20 30 40 NA

Редактировать: Глядя на функцию merge с getS3method('merge', 'data.frame'), row.names явно имеет значение NULL (это довольно длинный код, поэтому я не буду вставлять его сюда).

# Commenting 
# Lines 63 and 64
row.names(x) <- NULL
row.names(y) <- NULL

# and 
# Line 141 (thanks Ananda for pointing out)
attr(res, "row.names") <- .set_row_names(nrow(res))

и создание новой функции, скажем, MERGE, работает так, как OP предназначен для этого примера. Просто эксперимент.

person Arun    schedule 10.02.2013
comment
+1. Я всегда забываю о возможности слияния на "row.names" - person A5C1D2H2I1M1N2O1R2T1; 10.02.2013
comment
Что касается вашего редактирования, мне также пришлось удалить строку 141 (attr(res, "row.names") <- .set_row_names(nrow(res))). Я разместил здесь суть, которую можно загрузить и запустить с помощью library(devtools); source_gist(4750113); MERGE(x, y, all = TRUE), по крайней мере, через часть, подтверждающая ваши эксперименты. - person A5C1D2H2I1M1N2O1R2T1; 10.02.2013
comment
Давайте представим, что у вас есть третий df, z <- data.frame(a = c(11, 21), b = c(22, 32), d = c(33, 43), row.names = c("row_3", "another_row3")). Как заставить работать обычный merge (возможно, с Reduce или даже вручную)? MERGE работает, как и ожидалось, с Reduce(function(x, y) MERGE(x, y, all = TRUE, sort = FALSE), list(x, y, z)) (более или менее - меняется порядок столбцов), и RBIND(list(x, y, z)) тоже помогает. Но я не могу найти настоящее базовое решение merge здесь. Любые идеи? - person A5C1D2H2I1M1N2O1R2T1; 10.02.2013