如何转换 R tibble 中包含 NULL 值的列表中的列,以便输出是没有列表且 NA 替换 NULL 的 tibble

问题描述 投票:0回答:1

从 dplyrivot_wider 操作输出的 R tibble 创建一些字符列和其他列表列。我理解发生这种情况是因为在pivot_wider进程中存在一些重复的names_from组合。列表列还包含 NULL 值,列出标题时结果如下所示:

> head(test)
# A tibble: 6 × 4
  SAMPLE_NO SAMPLE_ANALYSIS_NO `SiO2_%_AES` `LOI_%_AES`
  <chr>     <chr>              <list>       <list>     
1 16821     11456              <chr [1]>    <chr [1]>  
2 16825     11461              <chr [1]>    <NULL>     
3 16829     11466              <chr [1]>    <chr [1]>  
4 16833     11471              <chr [1]>    <chr [1]>  
5 16836     11477              <chr [1]>    <chr [1]>  
6 16837     11479              <chr [1]>    <chr [1]>  

...在 RStudio 中查看时,标题看起来像这样:

这向我表明列表正在使用一些巧妙的过程来节省内存空间,因为在完整的 tibble 中,有数十万行和数千列,就像这里的示例一样。聪明的部分是列表只存储在特定列中找到的所有唯一值,例如在第一个列表列中只有 43 种可能的结果,然后使用这个结构(我不完全理解)来放置如果需要,则在一行中输入正确的值,否则为 NULL

现在我想转换这个 tibble,这样我就有一个没有列表列(仅字符列)的 tibble(或数据框),并且在输出中输出 NA 而不是 NULL。我已经在这个有趣的谜题上闲逛了几个小时,但现在是时候寻求一些帮助了,因为我被难住了。如果您希望提供帮助,示例数据就是这个链接的 RDS 对象

r dplyr
1个回答
0
投票

我建议,从长远来看,修复创建列表列的枢轴/重塑/聚合可能是值得的,但在短期内:

test <- tibble(SAMPLE_NO = 1:6, SAMPLE_ANALYSIS_NO = 11:16, SiO2 = as.list(letters[1:6]), LOI = replace(as.list(LETTERS[1:6]), 2, list(NULL)))
test
# # A tibble: 6 × 4
#   SAMPLE_NO SAMPLE_ANALYSIS_NO SiO2      LOI      
#       <int>              <int> <list>    <list>   
# 1         1                 11 <chr [1]> <chr [1]>
# 2         2                 12 <chr [1]> <NULL>   
# 3         3                 13 <chr [1]> <chr [1]>
# 4         4                 14 <chr [1]> <chr [1]>
# 5         5                 15 <chr [1]> <chr [1]>
# 6         6                 16 <chr [1]> <chr [1]>

library(dplyr)
test %>%
  mutate(across(c(SiO2, LOI), ~ sapply(.x, function(z) if (length(z)) z[[1]] else NA)))
# # A tibble: 6 × 4
#   SAMPLE_NO SAMPLE_ANALYSIS_NO SiO2  LOI  
#       <int>              <int> <chr> <chr>
# 1         1                 11 a     A    
# 2         2                 12 b     NA   
# 3         3                 13 c     C    
# 4         4                 14 d     D    
# 5         5                 15 e     E    
# 6         6                 16 f     F    

这完全依赖于长度为 0 或 1 的列表元素,仅此而已。如果还有更多,

z[[1]]
将默默地丢弃单元格的剩余元素。虽然这并不假设所有元素都是同一类,但如果某些元素不是字符串并且至少有一个是字符串,这将是一个副作用,因为所有元素都将被强制为
character

© www.soinside.com 2019 - 2024. All rights reserved.