我们可以使用na.omit
t(apply(df, 1, na.omit))
# [,1] [,2]
#VEG PUFF 12 78.43
#CHICKEN PUFF 16 88.24
#BAKERY Total 28 84.04
更新
根据excel数据显示
lst <- apply(df, 1, na.omit)
df2 <- do.call(rbind, lapply(lst, `length<-`, max(lengths(lst))))
row.names(df2) <- row.names(df)
或者另一个选项是来自data.table的melt/dcast
library(data.table)
dcast(melt(setDT(df1, keep.rownames=TRUE), id.var = 'rn',
na.rm = TRUE), rn~ paste0("c", rowid(rn)), value.var = "value")
# rn c1 c2 c3
#1: BAKERY Total 28 84.04 NA
#2: CHICKEN PUFF 16 88.24 143
#3: VEG PUFF 12 78.43 NA
为了提供一个可重现的例子,
df1 <- structure(list(c1 = c(NA, NA, NA), c2 = c(12L, 16L, NA), c3 = c(NA,
NA, 28L), c4 = c(NA, 88.24, NA), c5 = c(78.43, 143, 84.04)), .Names = c("c1",
"c2", "c3", "c4", "c5"), class = "data.frame", row.names = c("VEG PUFF",
"CHICKEN PUFF", "BAKERY Total"))
lst <- lapply(seq_len(nrow(df1)), function(i) {
x1 <- unlist(df1[i,])
x1[complete.cases(x1)]})
df2 <- do.call(rbind, lapply(lst, `length<-`, max(lengths(lst))))
row.names(df2) <- row.names(df1)
上述方法与apply方法类似,不同之处在于我们总是可以确定这个输出一个list(在apply中-它可以变化。当元素数量相同时删除NA,它将输出一个matrix,在其他情况下输出一个list)。因此,我们遍历行序列,删除NA 元素,在末尾填充NA 以使list 元素的长度相同,然后rbind
或者另一个选项是which 和arr.ind=TRUE
ind <- which(!is.na(df), arr.ind=TRUE)
matrix(df[ind[order(ind[,1]),]], ncol=2, byrow=TRUE,
dimnames = list(row.names(df), paste0("c", 1:2)))
# c1 c2
#VEG PUFF 12 78.43
#CHICKEN PUFF 16 88.24
#BAKERY Total 28 84.04