Самый простой способ заставить rbind игнорировать имена столбцов

Это возникло как раз в ответ на другой вопрос. Когда вы rbind два фрейма данных, столбцы сопоставляются по имени, а не по индексу, что может привести к неожиданному поведению:

> df<-data.frame(x=1:2,y=3:4)
> df
  x y
1 1 3
2 2 4
> rbind(df,df[,2:1])
  x y
1 1 3
2 2 4
3 1 3
4 2 4

Конечно, есть обходные пути. Например:

rbind(df,rename(df[,2:1],names(df)))
data.frame(rbind(as.matrix(df),as.matrix(df[,2:1])))

При редактировании: rename из пакета plyr на самом деле не работает таким образом (хотя я думал, что у меня это работает, когда я изначально писал это ...). Чтобы сделать это путем переименования, используйте решение SimonO101:

rbind(df,setNames(df[,2:1],names(df)))

Кроме того, как ни странно,

data.frame(rbindlist(list(df,df[,2:1])))

работает по индексу (и если мы не возражаем против таблицы данных, то она довольно лаконична), так что в этом разница между do.call(rbind).

Вопрос в том, как наиболее кратко rbind два фрейма данных, имена которых не совпадают? Я знаю, что это кажется тривиальным, но такие вещи могут загромождать код. И я не хочу писать новую функцию с именем rbindByIndex. В идеале это было бы что-то вроде rbind(df,df[,2:1],byIndex=T).


person mrip    schedule 10.10.2013    source источник
comment
Интересный. Хотя лично я бы предпочел, чтобы rbind на фреймах данных позаботился о сопоставлении именованных подмножеств (то есть столбцов). Если вы не хотите отслеживать объекты по имени, используйте в первую очередь matrix?   -  person Carl Witthoft    schedule 10.10.2013
comment
Одна (возможно, единственная) причина не использовать matrix состоит в том, что он не позволяет смешивать типы.   -  person mrip    schedule 10.10.2013


Ответы (2)


Здесь тебе может пригодиться setNames ...

rbind(df, setNames(rev(df), names(df)))
#  x y
#1 1 3
#2 2 4
#3 3 1
#4 4 2

Я подозреваю, что ваш реальный вариант использования несколько сложнее. Вы, конечно, можете изменить порядок столбцов в первом аргументе setNames по своему усмотрению, просто используйте names(df) во втором аргументе, чтобы имена переупорядоченных столбцов совпадали с оригиналом.

person Simon O'Hanlon    schedule 10.10.2013
comment
Спасибо, я использовал rename из пакета plyr, и теперь, когда я пытаюсь повторно запустить свой код из OP, он не работает. - person mrip; 10.10.2013
comment
@Thomas да, это действительно удобная маленькая функция! - person Simon O'Hanlon; 10.10.2013
comment
@mrip хорошо, я надеюсь, что это будет полезно для вашего реального использования! - person Simon O'Hanlon; 10.10.2013
comment
@ SimonO101 Мне нравится простота кода внутри setNames. - person Roland; 10.10.2013
comment
Это не игнорирует, не так ли? Он просто устанавливает одинаковые имена. - person ifly6; 08.03.2018

Это кажется довольно простым:

mapply(c,df,df[,2:1])
     x y
[1,] 1 3
[2,] 2 4
[3,] 3 1
[4,] 4 2

Однако в этом простом случае вы должны превратить его обратно в фрейм данных (потому что mapply упрощает его до матрицы):

as.data.frame(mapply(c,df,df[,2:1]))
  x y
1 1 3
2 2 4
3 3 1
4 4 2

Важное примечание 1. Похоже, что существует обратная сторона приведения типов, когда ваш фрейм данных содержит векторы разных типов:

df<-data.frame(x=1:2,y=3:4,z=c('a','b'))
mapply(c,df,df[,c(2:1,3)])
     x y z
[1,] 1 3 2
[2,] 2 4 1
[3,] 3 1 2
[4,] 4 2 1

Важное примечание 2. Также ужасно, если у вас есть факторы.

df<-data.frame(x=factor(1:2),y=factor(3:4))
mapply(c,df[,1:2],df[,2:1])
     x y
[1,] 1 1
[2,] 2 2
[3,] 1 1
[4,] 2 2

Итак, пока у вас есть все числовые данные, все в порядке.

person Thomas    schedule 10.10.2013
comment
Но у вас возникнут проблемы, если у вас будут разные типы данных в df. - person Roland; 10.10.2013
comment
@Roland Ага, я только что отредактировал для этого. Во всяком случае, вокруг этого? - person Thomas; 10.10.2013
comment
Да, напишите функцию rbindByIndex, которую OP явно не хочет делать ... - person Roland; 10.10.2013
comment
Если у вас нет факторов, вы можете заставить это работать со смешанными типами с помощью data.frame(mapply(c(df,df[,c(2,1,3)]),SIMPLIFY=F)), но тогда это будет не так красиво и лаконично. - person mrip; 10.10.2013
comment
Или используйте Map, который равен mapply(...,SIMPLIFY=FALSE) - data.frame(Map(c,df,df[,2:1])) - person thelatemail; 11.10.2018