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

时间:2015-07-24 21:05:45

标签: r data-manipulation

我有一个数据框,其格式如下

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

请注意,每列中的值/行数会有所不同(NAs /空值)。

我希望结果看起来像这样:

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

你能否为我的问题建议一个快速的解决方案?

优雅解决方案

感谢nongkrongakrun的答案。 我不了解速度,但完成工作的最优雅的解决方案如下:

  • my_final = data.frame(VALUE=unlist(my_data[c(TRUE,FALSE)]), ID=unlist(my_data[c(FALSE, TRUE)]))
  • my_final = setNames(data.frame(lapply(split(as.list(my_data), c(F, T)), unlist)), c("VALUE", "ID"))

还要省略空行:

  • my_final_trimmed = my_final[complete.cases(my_final), ]

3 个答案:

答案 0 :(得分:2)

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

我们转换了' data.frame'到' data.table' (setDT(df1))。使用melt,我们将measure参数与regex patterns列的名称一起指定为' ID'和' VALUE'。可选参数包括命名'值'列为value.name,并使用NA删除na.rm=TRUE值。如果我们不需要'变量'列,可以将其分配(:=)为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 :(得分:1)

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

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

答案 2 :(得分:1)

另一个基础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