簡體   English   中英

將R數據框中的列表展開為數據框的其他行?

[英]Expand an list in an R dataframe into additional rows of the dataframe?

今天早些時候另一個問題中,我詢問如何將嵌套列表展平為數據幀中的一行。 我希望進一步了解如何在數據框中操作我的列表,這次是通過在數據框中垂直擴展列表,添加新行來容納數據。

在這種情況下,我希望從這個結構:

CAT    COUNT            TREAT
A      1,2,3            Treat-a, Treat-b
B      4,5              Treat-c,Treat-d,Treat-e

對於這種結構:

CAT   COUNT  TREAT
A     1      Treat-a   
A     2      Treat-b
A     3      NA 
B     4      Treat-c 
B     5      Treat-d
B     NA     Treat-e

用於生成測試(源)數據的代碼:

df<-data.frame(CAT=c("A","B"))
df$COUNT <-list(1:3,4:5) # as numbers
df$TREAT <-list(paste("Treat-", letters[1:2],sep=""),paste("Treat-", letters[3:5],sep=""))

我嘗試使用CBIND的方法類似於我之前提到的問題的答案,但由於多個列表之間的值不同,它失敗了。 感謝您的耐心,因為我試圖掌握這些基本的操作任務。

這是我想出來的,使用輔助函數cbind.fill :( 用空df(cbind.fill?)cbd df

cbind.fill <- function(...){
  nm <- list(...) 
  nm <- lapply(nm, as.matrix)
  n <- max(sapply(nm, nrow)) 
  do.call(cbind, lapply(nm, function (x) 
    rbind(x, matrix(, n-nrow(x), ncol(x))))) 
}

#Split df by CAT
df.split <- split(df, df$CAT)

#Apply cbind.fill to make a matrix filled with NA where needed
rawlist <- lapply(df.split, function(x) cbind(as.character(x$CAT), cbind.fill(unlist(x$COUNT), unlist(x$TREAT) ) ))  

#Bind rows and convert matrix to data.frame
df.new <- as.data.frame(do.call(rbind, rawlist))

#Column names
colnames(df.new) <- names(df)

df.new
  CAT COUNT   TREAT
1   A     1 Treat-a
2   A     2 Treat-b
3   A     3    <NA>
4   B     4 Treat-c
5   B     5 Treat-d
6   B  <NA> Treat-e

從前一個問題擴展我的答案 ,你可以創建另一個函數,讓我們稱之為flattenLong ,它將“data.table”中的flattenmelt結合起來,以獲得所需的輸出。

該函數如下所示:

flattenLong <- function(indt, cols) {
  ob <- setdiff(names(indt), cols)
  x <- flatten(indt, cols, TRUE)
  mv <- lapply(cols, function(y) grep(sprintf("^%s_", y), names(x)))
  setorderv(melt(x, measure.vars = mv, value.name = cols), ob)[]
}

用法很簡單:

flattenLong(df, c("COUNT", "TREAT"))
##    CAT variable COUNT   TREAT
## 1:   A        1     1 Treat-a
## 2:   A        2     2 Treat-b
## 3:   A        3     3      NA
## 4:   B        1     4 Treat-c
## 5:   B        2     5 Treat-d
## 6:   B        3    NA Treat-e

為方便起見,這里再次flatten了:

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[]
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM