在 R 中按行绑定数据帧的多列的最佳方法

Best way to bind several columns of a dataframe by row in R

我有一个具有以下形式的数据框

ID1 | VALUE |ID2 | VALUE | ID3 | VALUE
111  | one   |333 | three | 555 | five
222  | two   |    | NA    | 666 | six

请注意,每列中 values/rows 的数量各不相同(NAs/empty 个值)。

我希望结果如下所示:

ID  | VALUE 
111 | one
222 | two
333 | three
555 | five
666 | six

我尝试了以下方法:

x = as.matrix(df)
x= matrix(x,ncol = 2)

此过程混合了某些列的 ID 和 VALUE。我的猜测是这是因为 NA 和 NULL 值。

ID  | VALUE 
111 | one
222 | two
333 | three
five| 555
six | 666

你能为我的问题提出一个快速的解决方案吗?

优雅的解决方案

感谢 nongkrong and akrun 的回答。 我不知道速度如何,但完成工作的最优雅的解决方案如下:

还要省略空行:

一个选项是使用 data.table 的开发版本中的 melt。安装开发版本的说明是 here.

我们将 'data.frame' 转换为 'data.table' (setDT(df1))。使用 melt,我们将 measure 参数指定为 regex patterns 以 'ID' 和 'VALUE' 开头的列名。可选参数包括命名 'value' 列,即 value.name 并使用 na.rm=TRUE 删除 NA 值。如果我们不需要 'variable' 列,可以将其分配 (:=) 为 NULL。

library(data.table)#v1.9.5+
melt(setDT(df1), measure= patterns("^ID", "^VALUE"), 
   value.name= c("ID", "VALUE"), na.rm=TRUE)[,variable:=NULL][]
#   ID VALUE
#1: 111   one
#2: 222   two
#3: 333 three
#4: 555  five
#5: 666   six

数据

df1 <- structure(list(ID1 = c(111L, 222L), VALUE = c("one", "two"), 
ID2 = c(333L, NA), VALUE.1 = c("three", NA), ID3 = c(555L, 
666L), VALUE.2 = c("five", "six")), .Names = c("ID1", "VALUE", 
"ID2", "VALUE.1", "ID3", "VALUE.2"), class = "data.frame",
row.names = c(NA, -2L))

抱歉,如果这个答案对你的情况来说太具体了,但是采用那种形式的数据框,答案是平易近人的(不优雅的)如下:

1) 消灭列名

colnames(dataframe_name) <- NULL

2) 通过子集拆分成更小的数据帧

df1 <- dataframe_name[, 1:2]  # columns 1-2
df2 <- dataframe_name[, 3:4]  # columns 3-4
df3 <- dataframe_name[, 5:6]  # columns 5-6

3) 将列名添加到数据框中

f <- function(df) {
    colnames(df) <- c('ID', 'VALUE')  # set colnames for df with 2 cols
    return(df)
} # function to apply to each df

l <- list(df1, df2, df3)
list_of_frames <- lapply(l, f)  # apply colname function to each

4) 将数据框绑定在一起

do.call(rbind, list_of_frames)  # call rbind (row bind) on each frame

另一个基数R,使用split分隔交替列

res <- setNames(
    data.frame(lapply(split(as.list(dat), c(F, T)), unlist))
  , c("VALUE", "ID"))

res[complete.cases(res), ]
#      VALUE      ID
# ID11   111  one   
# ID12   222  two   
# ID21   333  three 
# ID31   555    five
# ID32   666     six