Có một câu trả lời đã xóa ở đây chỉ ra rằng "splitstackshape" có thể được sử dụng cho điều này . Nó có thể, nhưng câu trả lời đã xóa sử dụng chức năng sai. Thay vào đó, nó nên sử dụng hàm listCol_w
. Thật không may, trong hình thức hiện tại của nó, chức năng này không được vectorized trên các cột, vì vậy bạn sẽ cần phải lồng các cuộc gọi đến listCol_w
cho mỗi cột cần được làm phẳng.
Dưới đây là cách tiếp cận:
library(splitstackshape)
listCol_w(listCol_w(df, "COUNT", fill = NA), "TREAT", fill = NA)
## CAT COUNT_fl_1 COUNT_fl_2 COUNT_fl_3 TREAT_fl_1 TREAT_fl_2 TREAT_fl_3
## 1: A 1 2 3 Treat-a Treat-b NA
## 2: B 4 5 NA Treat-c Treat-d Treat-e
Lưu ý rằng fill = NA
đã được xác định bởi vì nó mặc định là fill = NA_character_
, mà nếu không sẽ ép buộc tất cả các giá trị để nhân vật.
Một giải pháp thay thế khác là sử dụng transpose
từ "data.table". Đây là một thực hiện có thể (trông đáng sợ, nhưng sử dụng chức năng là dễ dàng). Lợi ích là (1) bạn có thể chỉ định các cột để làm phẳng, (2) bạn có thể quyết định xem bạn muốn thả cột ban đầu hay không, và (3) nó nhanh.
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[]
}
Cách sử dụng sẽ là ...
Giữ cột gốc:
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
Thả cột gốc:
flatten(df, c("COUNT", "TREAT"), TRUE)
# CAT COUNT_1 COUNT_2 COUNT_3 TREAT_1 TREAT_2 TREAT_3
# 1: A 1 2 3 Treat-a Treat-b NA
# 2: B 4 5 NA Treat-c Treat-d Treat-e
Xem this gist để so sánh với các giải pháp khác được đề xuất.
Dữ liệu 'thực' của bạn lớn đến mức nào (hiệu suất có phải là vấn đề không?) – Heroka
cSplit() từ gói splitstackshape sẽ là một lựa chọn tốt. – jazzurro
Với ví dụ của bạn 'df [2: 3] <- lapply (df [, 2: 3], hàm (x) do.call (rbind, lapply (x," [", 1: 3)))' có vẻ là một khởi đầu tốt đẹp. – nicola