取消嵌套不同大小的相关列表列

Posted

技术标签:

【中文标题】取消嵌套不同大小的相关列表列【英文标题】:Unnesting related list-columns of different size 【发布时间】:2020-09-03 17:18:52 【问题描述】:

解析 xml 文件后,我的数据如下所示:

example_df <-  
  tibble(id = "ABC",
         wage_type = "salary",
         name = c("Description","Code","Base",
                  "Description","Code","Base",
                  "Description","Code"),
         value = c("wage_element_1","51B","600",
                   "wage_element_2","51C","740",
                   "wage_element_3","51D"))

example_df 

# A tibble: 8 x 4
  id    wage_type name        value         
  <chr> <chr>     <chr>       <chr>         
1 ABC   salary    Description wage_element_1
2 ABC   salary    Code        51B           
3 ABC   salary    Base        600           
4 ABC   salary    Description wage_element_2
5 ABC   salary    Code        51C           
6 ABC   salary    Base        740           
7 ABC   salary    Description wage_element_3
8 ABC   salary    Code        51D      

大约有 1000 个不同的 id,每个都有 wage_type 的三个可能值。 我想将name 列中的值更改为列。 我尝试使用pivot,但我正在努力处理生成的list-cols:因为并非所有salary 都有Base,因此生成的列表列的大小不同,如下所示:

example_df <- example_df %>%
  pivot_wider(id_cols = c(id, wage_type),
              names_from = name,
              values_from = value)

example_df

# A tibble: 1 x 5
  id    wage_type Description Code      Base     
  <chr> <chr>     <list>      <list>    <list>   
1 ABC   salary    <chr [3]>   <chr [3]> <chr [2]>

因此,当我尝试取消嵌套 cols 时,它会引发错误:

example_df%>%
  unnest(cols = c(Description,Code,Base))

Error: Can't recycle `Description` (size 3) to match `Base` (size 2).

我知道这是因为 tidyr 函数不会回收,但我找不到解决此问题的方法或base r解决我的问题。我试图用 unlist(strsplit(as.character(x)) 按照how to split one row into multiple rows in R 的解决方案,但也遇到了列长度问题。

想要的输出如下:

desired_df <- 
  tibble(
    id=c("ABC","ABC","ABC"),
    wage_type=c("salary","salary","salary"),
    Description = c("wage_element_1","wage_element_2","wage_element_3"),
    Code = c("51B","51C","51D"),
    Base = c("600","740",NA))

desired_df

id    wage_type Description    Code  Base 
  <chr> <chr>     <chr>          <chr> <chr>
1 ABC   salary    wage_element_1 51B   600  
2 ABC   salary    wage_element_2 51C   740  
3 ABC   salary    wage_element_3 51D   NA  

我希望有一个 tidyr 解决方案,但我们将不胜感激。谢谢。

【问题讨论】:

【参考方案1】:

我建议使用tidyverse 函数的这种方法。您遇到的问题是由于函数如何管理不同的行。因此,通过创建像 id2 这样的 id 变量,您可以避免在最终重组数据中出现列表输出:

library(tidyverse)
#Code
example_df %>% 
  arrange(name) %>%
  group_by(id,wage_type,name) %>%
  mutate(id2=1:n()) %>% ungroup() %>%
  pivot_wider(names_from = name,values_from=value) %>%
  select(-id2)

输出:

# A tibble: 3 x 5
  id    wage_type Base  Code  Description   
  <chr> <chr>     <chr> <chr> <chr>         
1 ABC   salary    600   51B   wage_element_1
2 ABC   salary    740   51C   wage_element_2
3 ABC   salary    NA    51D   wage_element_3

【讨论】:

以上是关于取消嵌套不同大小的相关列表列的主要内容,如果未能解决你的问题,请参考以下文章

取消嵌套命名列表列时保留名称

在Python中的列中将不同大小的列表写入csv

如何取消包含列表和字符条目的小标题列表列(“无法组合列表和字符”)?

两个布尔列/列表是不是匹配?两个不同大小的列的比较:一个列表的一部分是不是与另一个列表的一部分匹配? (Python)

循环嵌套数组生成不同长度的表

PyQt:如何为单个标题设置不同的标题大小?