【问题标题】:Summarise across list columns, get first value, in dplyr在 dplyr 中汇总列表列,获取第一个值
【发布时间】:2020-10-02 01:13:26
【问题描述】:

我有一个大型数据框,其中包含一些半重复的条目,我正在尝试通过 dplyr::summarise 合并。这适用于数字、字符和逻辑列,但不适用于列表列。

mydata <- tibble(A = c(1,1,2,2,3,3),
                 B = c(1,NA,4,5,7,7),
                 C = list(1:3, 1:3, 2:4, 2:4, 3:6, 3:6))

dedupedData <- mydata %>%
  group_by(A) %>%
  summarise(across(where(is.numeric), mean, na.rm = TRUE))

按预期工作;

dedupedData <- mydata %>%
  group_by(A) %>%
  summarise(across(where(is.numeric), mean, na.rm = TRUE),
            across(where(is.list), first))

与我的数据集不同。上面通过展开 C 的范围来创建重复的行数,即组 A1 得到 1:3,A2 得到 2:4,A3 得到 3:6。对于我的数据:

dedupedData <- mydata %>%
  group_by(A, B) %>%
  summarise(across(where(is.numeric), mean, na.rm = TRUE),
            across(where(is.character), first),
            across(where(is.logical), first),
            across(where(is.POSIXct), first),
            across(where(is.list), first))

在我包含 is.list 行之前一直有效,因此它会中断:

错误:summarise() 输入 ..5 有问题。 x '名称' 属性 [11] 必须与向量 [9] 长度相同

有谁知道如何解决这个问题?分组时,希望列表项与其他列一样拆分,因此组 A1 的 C 值应该是

mydata$C[1:2]

[1]11 2 3

[[2]]11 2 3

(第一个列表项是 R 中的方括号,但由于某种原因不在此处)

因此first(mydata$C[1:2])

11 2 3

看起来不错,我只需要将它发送到目标单元格。

我还需要以这种方式明确链接across 行吗?我试过!is.numeric,也试过is.POSIXct | is.character | is.logical | is.list。

谢谢。相关地,如果有人知道如何创建不是很好的范围的列列表 - 我之前已经设法通过分组摘要来做到这一点,但是对于这个代表,我复制了 R For Data Science @ 987654325@,但它似乎不具有普遍性,即如果您将 mydata 的最后一行更改为

C = list(c(1,2,3), 1:3, 2:4, 2:4, 3:6, 3:6))

那么 C1 将是 "c(1,2,3)" 而不是评估逗号分隔的术语,似乎不允许任何不是单个值或范围的东西?

干杯!

【问题讨论】:

  • 这个问题我不清楚。 across(where(is.list), first)) 返回每​​个 C 列中的第一个值,分别为 1:3、2:4 和 3:6,因为您正在输出中。如果那不是您想要的,您可以显示您的预期输出吗?

标签: r dplyr summary across


【解决方案1】:

我们按“A”、“B”分组,得到list的first元素,并将其包装在across中的list中

library(dplyr)
out <- mydata %>%
  group_by(A, B) %>% 
  summarise(across(where(is.numeric), mean, na.rm = TRUE), 
            across(where(is.list),  ~ list(first(.)))) 

-输出

out
# A tibble: 5 x 3
# Groups:   A [3]
#      A     B C        
#  <dbl> <dbl> <list>   
#1     1     1 <int [3]>
#2     1    NA <int [3]>
#3     2     4 <int [3]>
#4     2     5 <int [3]>
#5     3     7 <int [4]>

如果我们想获取第一个元素,另一个选项是slice

mydata %>% 
     group_by(A, B) %>%
     slice(1)

【讨论】:

  • 已经完成了 - 谢谢您,对于延迟回复感到抱歉。应该添加到管道中:%&gt;% select(colnames(mydata)) 重新排序 cols 以匹配原始。你有关于where 中波浪号构造的任何信息吗?并且必须在first 中明确输入(.) 吗?我认为这与波浪号有​​关。再次感谢!
  • @dez93_2000 你是说where(~ is.numeric(.))
  • 抱歉,不,where(is.list), ~ list(first(.)。谢谢。事实证明,我需要使用across(where(is.list), ~ list(unlist(., recursive = FALSE))) 实现的列表的第一个非空元素
  • 按照类似的思路,经过总结,我现在正在寻找变异以在列表列中将 NULL 替换为 NA,但结果不足。尝试(RHS)~ list(ifelse(is.null(.), NA, .)) 和类似但怀疑我可能需要以某种方式整合unlist...任何想法都非常感谢!
  • @dez93_2000 你可以在mutate 中使用map(., ~ replace(., is.null(.), NA))
猜你喜欢
  • 2021-08-16
  • 1970-01-01
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 2015-07-15
  • 2014-12-02
  • 2020-04-08
  • 1970-01-01
相关资源
最近更新 更多