목록 목록을 데이터 프레임으로 변환

Aug 30 2020

다양한 수의 요소와 함께 다양한 수의 문자 벡터를 포함하는 여러 다른 목록이 포함 된 목록이 있습니다. 각 목록이 행으로 표시되고 해당 목록 내의 각 문자 벡터가 열이되는 데이터 프레임을 만들고 싶습니다. 문자형 벡터에 1 개 이상의 요소가있는 경우 요소는 "+"기호를 사용하여 연결 및 분리되므로 하나의 문자열로 저장할 수 있습니다. 데이터는 다음과 같습니다.

fruits <- list(
  list(c("orange"), c("pear")),
  list(c("pear", "orange")),
  list(c("lemon", "apple"),
       c("pear"),
       c("grape"),
       c("apple"))
)

예상되는 출력은 다음과 같습니다.

fruits_df <- data.frame(col1 = c("orange", "pear + orange", "lemon + apple"),
           col2 = c("pear", NA, "pear"), 
           col3 = c(NA, NA, "grape"),
           col4 = c(NA, NA, "apple"))

목록에 포함될 수있는 문자형 벡터의 수에는 제한이 없으므로 솔루션은 열을 동적으로 생성해야하므로 열 수가 가장 많은 문자를 포함하는 목록의 길이와 동일한 df가 생성됩니다. 벡터.

답변

2 RonakShah Aug 31 2020 at 03:01

의 모든 목록에 fruits대해 하나의 행 데이터 프레임을 만들고 데이터를 바인딩 할 수 있습니다.

dplyr::bind_rows(lapply(fruits, function(x) as.data.frame(t(sapply(x, 
                 function(y) paste0(y, collapse = "+"))))))

#           V1   V2    V3    V4
#1      orange pear  <NA>  <NA>
#2 pear+orange <NA>  <NA>  <NA>
#3 lemon+apple pear grape apple
2 MrFlick Aug 31 2020 at 02:58

이것은 약간 지저분하지만 여기에 한 가지 방법이 있습니다.

cols <-  lapply(fruits, function(x) sapply(x, paste, collapse=" + "))
ncols <- max(lengths(cols))
dd <- do.call("rbind.data.frame", lapply(cols, function(x) {length(x) <- ncols; x}))
names(dd)  <- paste0("col", 1:ncol(dd))
dd

#            col1 col2  col3  col4
# 1        orange pear  <NA>  <NA>
# 2 pear + orange <NA>  <NA>  <NA>
# 3 lemon + apple pear grape apple

또는 다른 전략

ncols <- max(lengths(fruits))
dd <- data.frame(lapply(seq.int(ncols), function(x) sapply(fruits, function(y) paste(unlist(y[x]), collapse=" + "))))
names(dd)  <- paste0("col", 1:ncols)
dd

그러나 실제로는 목록에서 각 열이나 행을 만든 다음 함께 결합해야합니다.

1 JorisC. Aug 31 2020 at 07:14

rrapply::rrapply다음을 사용하여 목록을 data.frame에 녹인 다음 필요한 형식으로 캐스팅하는 또 다른 방법은 다음과 data.table::dcast같습니다.

library(rrapply)
library(data.table)

## melt to long data.frame
long <- rrapply(fruits, f = paste, how = "melt", collapse = " + ")

## cast to wide data.table
setDT(long)
dcast(long[, .(L1, L2, value = unlist(value))], L1 ~ L2)[, !"L1"]
#>              ..1  ..2   ..3   ..4
#> 1:        orange pear  <NA>  <NA>
#> 2: pear + orange <NA>  <NA>  <NA>
#> 3: lemon + apple pear grape apple