这里有一个已删除的答案指出可以使用"splitstackshape"来实现,但是该答案使用了错误的函数。相反,应该使用listCol_w
函数。不幸的是,在其当前形式下,该函数不能跨列向量化,因此您需要为每个需要展平的列嵌套调用listCol_w
函数。
以下是具体步骤:
library(splitstackshape)
listCol_w(listCol_w(df, "COUNT", fill = NA), "TREAT", fill = NA)
请注意,指定了
fill = NA
是因为它的默认值为
fill = NA_character_
,否则会将所有值强制转换为字符。
另一种选择是使用"data.table"中的
transpose
。这里是一个可能的实现(看起来很吓人,但使用该函数很容易)。好处是(1)您可以指定要展开的列,(2)您可以决定是否删除原始列,以及(3)速度很快。
flatten <- function(indt, cols, drop = FALSE) {
require(data.table)
if (!is.data.table(indt)) indt <- as.data.table(indt)
x <- unlist(indt[, lapply(.SD, function(x) max(lengths(x))), .SDcols = cols])
nams <- paste(rep(cols, x), sequence(x), sep = "_")
indt[, (nams) := unlist(lapply(.SD, transpose), recursive = FALSE), .SDcols = cols]
if (isTRUE(drop)) {
indt[, (nams) := unlist(lapply(.SD, transpose), recursive = FALSE),
.SDcols = cols][, (cols) := NULL]
}
indt[]
}
使用方法如下:
保留原始列:
flatten(df, c("COUNT", "TREAT"))
# CAT COUNT TREAT COUNT_1 COUNT_2 COUNT_3 TREAT_1 TREAT_2 TREAT_3
# 1: A 1,2,3 Treat-a,Treat-b 1 2 3 Treat-a Treat-b NA
# 2: B 4,5 Treat-c,Treat-d,Treat-e 4 5 NA Treat-c Treat-d Treat-e
删除原始列:
flatten(df, c("COUNT", "TREAT"), TRUE)
请参考此代码片段,以与其他提议的解决方案进行比较。