【问题标题】:Using tidyverse to "unnest" a data.frame column inside a tibble使用 tidyverse 在 tibble 中“取消嵌套” data.frame 列
【发布时间】:2021-04-25 04:17:08
【问题描述】:

我正在处理从 www 调用返回的一些数据,jsonliteas_tibble 以某种方式转换为 data.frame 列。

result 数据有一个Id 整数列和一个ActionCode data.frame 列,其中包含两个内部列。这些在控制台中显示为:

> result
# A tibble: 117 x 2
  Id    ActionCode$Code $Name 
  <int> <chr>           <chr>
  1     A1              First Code
  2     A2              Second Code
  3     A3              Third Code
  4     A4              Fourth Code
  ...

这可以用str()作为检查:

> result %>% str()
tibble [117 x 2] (S3: tbl_df/tbl/data.frame)
 $ Id : int [1:117] 1 2 3 4 ...
 $ ActionCode:'data.frame': 117 obs. of  2 variables:
  ..$ Code: chr [1:117] "A1" "A2" "A3" "A4" ...
  ..$ Name: chr [1:117] "First Code" "Second Code" "Third Code" "Fourth Code" ...

我已经从例如https://tibble.tidyverse.org/articles/types.html 这种data.frame 列是完全合法的,但我正在努力研究如何从整洁的 dplyr 管道访问此列中的数据 - 例如我不能select(ActionCode$Code)

有没有办法在dplyr 管道中使用这些列?或者有没有办法以某种方式展平这些列,类似于 unnest 可以在 list 列上使用的方式(尽管我在这里意识到我没有创建额外的行 - 我只是展平列层次结构)。

即我正在尝试找到一个可以输出的函数foo

> result %>% foo() %>% str()
tibble [117 x 2] (S3: tbl_df/tbl/data.frame)
 $ Id : int [1:117] 1 2 3 4 ...
 $ Code: chr [1:117] "A1" "A2" "A3" "A4" ...
 $ Name: chr [1:117] "First Code" "Second Code" "Third Code" "Fourth Code" ...

我无法提供 www 调用作为示例,但作为一个工作示例,我认为我看到的数据类型类似于:

sample_data <- tibble(
  Id = 1:10,
  ActionCode = tibble(
    Code = paste0("Id", 1:10),
    Name = paste0("Name ", 1:10),
  )
)

【问题讨论】:

    标签: r dataframe dplyr tidyr tibble


    【解决方案1】:

    另一种解决方案有效,但我仍然想指出data.table 可以很好地自动处理这些情况:

    library(tibble)
    
    sample_data <- tibble(
      Id = 1:10,
      ActionCode = tibble(
        Code = paste0("Id", 1:10),
        Name = paste0("Name ", 1:10),
      )
    )
    
    library(data.table)
    as.data.table(sample_data)
    #>     Id ActionCode.Code ActionCode.Name
    #>  1:  1             Id1          Name 1
    #>  2:  2             Id2          Name 2
    #>  3:  3             Id3          Name 3
    #>  4:  4             Id4          Name 4
    #>  5:  5             Id5          Name 5
    #>  6:  6             Id6          Name 6
    #>  7:  7             Id7          Name 7
    #>  8:  8             Id8          Name 8
    #>  9:  9             Id9          Name 9
    #> 10: 10            Id10         Name 10
    

    【讨论】:

      【解决方案2】:

      使用do.call 重新转换为data.frame 会使列变平

      library(dplyr)
      library(stringr)
      do.call(data.frame, sample_data) %>% 
          rename_at(vars(starts_with('ActionCode')), ~ 
              str_remove(., 'ActionCode\\.')) %>% 
          as_tibble
      

      -输出

      # A tibble: 10 x 3
      #      Id Code  Name   
      #   <int> <chr> <chr>  
      # 1     1 Id1   Name 1 
      # 2     2 Id2   Name 2 
      # 3     3 Id3   Name 3 
      # 4     4 Id4   Name 4 
      # 5     5 Id5   Name 5 
      # 6     6 Id6   Name 6 
      # 7     7 Id7   Name 7 
      # 8     8 Id8   Name 8 
      # 9     9 Id9   Name 9 
      #10    10 Id10  Name 10
      

      【讨论】:

        猜你喜欢
        • 2018-05-18
        • 1970-01-01
        • 2019-08-07
        • 1970-01-01
        • 2020-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-10
        相关资源
        最近更新 更多