我有一个数据框,其格式如下
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
你能否为我的问题建议一个快速的解决方案?
优雅解决方案
感谢nongkrong和akrun的答案。 我不了解速度,但完成工作的最优雅的解决方案如下:
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), ]
答案 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