การแปลงรายการเป็น dataframe

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คุณสามารถสร้าง dataframe หนึ่งแถวและผูกข้อมูลได้

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

อีกวิธีหนึ่งที่หลอมรวมรายการเป็น data.frame โดยใช้rrapply::rrapplyแล้วส่งไปยังรูปแบบที่ต้องการโดยใช้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