Как я могу связать векторы, соответствующие их именам столбцов?

rbind не проверяет имена столбцов при связывании векторов:

l = list(row1 = c(10, 20), row2 = c(20, 10))
names(l$row1) = c("A", "B")
names(l$row2) = c("B", "A")
l
$row1
 A  B 
10 20 

$row2
 B  A 
20 10 

rbind(l$row1, l$row2)
      A  B
[1,] 10 20
[2,] 20 10

Как я могу создать эту матрицу из ряда элементов списка, гарантируя, что имена столбцов правильно сопоставлены по строкам:

      A  B
[1,] 10 20
[2,] 10 20

person Robert Kubrick    schedule 06.06.2013    source источник


Ответы (6)


Вы можете использовать match:

l <- list(row1 = setNames(1:3, c("A", "B", "C")),
          row2 = setNames(1:3, c("B", "C", "A")),
          row3 = setNames(1:3, c("C", "A", "B")))

do.call(rbind, lapply(l, function(x) x[match(names(l[[1]]), names(x))]))

Результат:

     A B C
row1 1 2 3
row2 3 1 2
row3 2 3 1
person Sven Hohenstein    schedule 06.06.2013
comment
См. Ответ от @ scs76 ниже; это решение больше не нужно. - person Ashe; 14.03.2017
comment
Это все еще необходимо, если «строки» имеют разное количество элементов. - person JS1204; 02.08.2017

Кажется, что в текущих версиях R (у меня версия 3.3.0) rbind может объединять два набора данных с одинаковыми именами столбцов, даже если они находятся в разном порядке.

   df1 <- data.frame(a = c(1:5), c = c(LETTERS[1:5]),b=c(11:15))
   df2 <- data.frame(a = c(6:10), b = c(16:20),c=c(LETTERS[6:10]))
   rbind(df1,df2)
    a c  b
1   1 A 11
2   2 B 12
3   3 C 13
4   4 D 14
5   5 E 15
6   6 F 16
7   7 G 17
8   8 H 18
9   9 I 19
10 10 J 20
person scs76    schedule 07.09.2016
comment
Я считаю, что это верно только при объединении двух элементов. При попытке объединить три, третий связывается без совпадающих меток. Может кто-нибудь это подтвердить? - person Des Grieux; 09.04.2018
comment
Кажется, он отлично работает с тремя элементами в R версии 3.5.2: df1 <- data.frame(a = c(1:5), c = c(LETTERS[1:5]),b=c(11:15)) df2 <- data.frame(a = c(6:10), b = c(16:20),c=c(LETTERS[6:10])) df3 <- data.frame(c = c(LETTERS[11:13]), a = c(11:13), b = c(21:23)) rbind(df1, df2, df3) - person user29609; 26.02.2019

smartbind() будет соответствовать именам столбцов и допускать отсутствующие:

library(gtools)
do.call(smartbind,l)
      A  B
row1 10 20
row2 10 20
person Ari B. Friedman    schedule 06.06.2013
comment
plyr::rbind.fill - аналогичное решение. - person Ari B. Friedman; 09.07.2014

rbind будет работать, если вы сначала измените каждый элемент l на фрейм данных:

do.call("rbind", lapply(l, function(x) data.frame(as.list(x))))

      A  B
row1 10 20
row2 10 20
person SchaunW    schedule 06.06.2013
comment
Стрелять. Мэтью Плурд опередил меня. - person SchaunW; 06.06.2013
comment
+1! а также обратите внимание, что здесь интересно то, что классический эквивалент rbindlist из data.table не дает того же ответа, что и do.call(rbind,...) - person agstudy; 06.06.2013
comment
Приятной особенностью rbindlist является возможность довольно легко заполнять пустые значения с помощью NA. - person Brandon; 19.02.2015

Почему не просто rbind(l$row1, l$row2[names(l$row1)]). Также хорошо работает для фреймов данных. Обратите внимание, что при этом будут отброшены столбцы из l$row2, которые не отображаются в l$row1.

person David Roberts    schedule 21.03.2017

Уменьшение - мощная функция, но в некоторых случаях используется нечасто; вот альтернативная реализация

Это создаст rbind, в котором, если есть столбцы, которые не соответствуют «NA», будут сгенерированы для них.

rbindedFrame = Reduce(custom_rbind,listofDataframes)  

custom_rbind = function(x1,x2){
  c1 = setdiff(colnames(x1),colnames(x2))
  c2 = setdiff(colnames(x2),colnames(x1))
  for(c in c2){##Adding missing columns from 2 in 1
    x1[[c]]=NA
  }
  for(c in c1){##Similiarly ading missing from 1 in 2
    x2[[c]]=NA
  }
  x2 = x2[colnames(x1)]
  rbind(x1,x2)
}
}
person Yash    schedule 11.07.2018