代码之家  ›  专栏  ›  技术社区  ›  tassones

具有某些值列表的未命名数据帧

  •  1
  • tassones  · 技术社区  · 2 年前

    我正在尝试运行一个数据帧,其中一些列有值列表。理想情况下,这些值将以这样一种方式进行无测试,即每个值都会创建一个新行,并用 NA 如果值少于列表中的值。

    示例数据:

    dat <- data.frame(matrix(ncol = 4, nrow = 2))
    colnames(dat)[1:4] <- c("Date","value1","value2","value3")
    dat$Date <- c(as.Date('1968-06-13'), as.Date('1968-09-17'))
    dat$value1 <- c(list(c(79,78)),list(c(55,56,57)))
    dat$value2 <- c(list(c(7.3,7.2)),list(c(6.6,6.7)))
    dat$value3 <- c(0.27,0.55)
    View(dat)
    

    我尝试过:

    library(tidyverse)
    
    dat %>%
      unnest(cols = c(value1,value2,value3))
    
    # Error in `unnest()`: ! In row 2, can't recycle input of size 3 to size 2.
    
    

    ChatGPT建议:

    library(tidyr)
    
    # First suggestion
    dat %>%
      unnest_longer(cols = starts_with("value"), indices_to = "row") %>%
      pivot_wider(names_from = "row", values_from = starts_with("value"))
    
    # Second suggestion
    dat %>%
      unnest_wider(cols = starts_with("value"), names_sep = "_") %>%
      mutate(across(starts_with("value"), ~ ifelse(is.na(.), NA, as.numeric(.))))
    
    # both produce same error - Error in unnest_wider(., cols = starts_with("value"), names_sep = "_") : unused argument (cols = starts_with("value"))
    

    理想输出:

            Date value1 value2 value3
    1 1968-06-13     79    7.3   0.27
    2 1968-06-13     78    7.2     NA
    3 1968-09-17     55    6.6   0.55
    4 1968-09-17     56    6.7     NA
    5 1968-09-17     57     NA     NA
    
    3 回复  |  直到 2 年前
        1
  •  4
  •   I_O    2 年前

    也许不是最简洁的解决方案,但有效:

    library(dplyr)
    library(tidyr)
    
    dat |>
      pivot_longer(starts_with('value'), values_transform = as.list) |>
      unnest_longer(value) |>
      group_by(Date, name) |>
      mutate(i = row_number()) |>
      pivot_wider() |>
      select(-i)
    
    + # A tibble: 5 x 4
    # Groups:   Date [2]
      Date       value1 value2 value3
      <date>      <dbl>  <dbl>  <dbl>
    1 1968-06-13     79    7.3   0.27
    2 1968-06-13     78    7.2  NA   
    3 1968-09-17     55    6.6   0.55
    4 1968-09-17     56    6.7  NA   
    5 1968-09-17     57   NA    NA  
    
        2
  •  2
  •   ThomasIsCoding    2 年前

    也许你可以试试这个

    dat %>%
        mutate(value3 = as.list(value3)) %>%
        unnest(value1) %>%
        mutate(across(value2:value3, ~ `length<-`(.x[[1]], n())), .by = "Date")
    

    它给出

    # A tibble: 5 × 4
      Date       value1 value2 value3
      <date>      <dbl>  <dbl>  <dbl>
    1 1968-06-13     79    7.3   0.27
    2 1968-06-13     78    7.2  NA
    3 1968-09-17     55    6.6   0.55
    4 1968-09-17     56    6.7  NA
    5 1968-09-17     57   NA    NA
    
        3
  •  1
  •   Dubukay    2 年前

    这里有一个比@ThomasIsCoding的解决方案稍微详细但可能不那么密集的选项:

    dat %>%
      mutate(value3=as.list(value3)) %>%
      pivot_longer(starts_with("value")) %>%
      unnest_longer(value) %>%
      group_by(Date, name) %>%
      mutate(rn=row_number()) %>%
      ungroup() %>%
      complete(Date, name, rn) %>%
      pivot_wider() %>%
      select(-rn) %>%
      drop_na(value1)
    

    它给出了相同的