【问题标题】:Unnesting results of function returning multiple values in summarize在汇总中返回多个值的函数的取消嵌套结果
【发布时间】:2023-04-03 01:28:01
【问题描述】:

“想要的”结果由下面的“do”函数给出。我认为我可以通过使用 unnest 来获得相同的效果,但无法让它发挥作用。

library(dplyr)
library(tidyr)

# Function rr is given
rr = function(x){
  # This should be an expensive and possibly random function
  r = range(x + rnorm(length(x),0.1))
#  setNames(r, c("min", "max")) # fails, expecting single value
#  list(min = r[1], max= r[2]) # fails
  list(r) # Works, but result is in "long" form without min/max
}

# Works, but syntactically awkward
iris %>% group_by(Species) %>%
  do( {
    r = rr(.$Sepal.Width)[[1]]
    data_frame(min = r[1], max = r[2])
  })

# This give the long format, but without column
# names min/max
iris %>% group_by(Species) %>%
  summarize(
    range = rr(Sepal.Length)
  ) %>% unnest(range)

【问题讨论】:

  • @Bulat:上面的例子完全可以重现。此外,它被剥离了所有不必要的混乱。因此我不明白你的评论。
  • 我不知道 iris 数据集,我猜缺少的是所需的结果或有关不工作的详细信息。您提供了两个工作代码示例,不清楚哪里出了问题。
  • 第一个例子根本不是优雅的代码,即使结果是正确的。运行第二个,看看有什么不同。
  • 我认为目前这个问题没有好的解决方案。

标签: r dplyr tidyr


【解决方案1】:

这是一个使用 data.table 包的非常简单的替代方案

# Function rr is given
rr = function(x) as.list(setNames(range(x + rnorm(length(x), 0.1)), c("min", "max"))) 

library(data.table)
data.table(iris)[, rr(Sepal.Width), by = Species]
#       Species      min      max
# 1:     setosa 1.839845 6.341040
# 2: versicolor 1.063727 5.498810
# 3:  virginica 1.232525 5.402483

【讨论】:

  • 有了rr的定义,也可以使用iris %>% group_by(Species) %>% do(data.frame(rr(.$Sepal.Length)))
  • @docendodiscimus,是的,但是data.frame(按组)和do 都有些低效,因此,我更喜欢避免使用它们。我猜spreadunneset 效率也很低(但还没有检查过)。 as.list 应该是高效的 IMO。
  • 好吧,我并不是说它会比您的 data.table 方法更有效。这似乎值得一提,因为他的 Q 专门针对 dplyr 并带有 dplyr 标记
  • @docendodiscimus 好的,这是有道理的。您可以编辑、发布或保持原样 - 由您决定。
  • 有趣而简洁,但对我来说效率并不那么重要。而且我承认,几年前我曾经被错误地使用 data.table 的特殊语法所困扰。
【解决方案2】:

Unnest() 将始终以“长”格式取消列出嵌套列,但如果您创建 key 列,则可以使用 spread() 获得所需的输出。

library(dplyr)
library(tidyr)

iris %>%
  group_by(Species) %>%
  summarize(range = rr(Sepal.Length)) %>% 
  unnest(range) %>% mutate(newcols = rep(c("min", "max"), 3)) %>%
  spread(newcols, range)
#     Species      max      min
#      (fctr)    (dbl)    (dbl)
#1     setosa 7.636698 3.292692
#2 versicolor 9.792319 3.337382
#3  virginica 9.810723 3.367066

【讨论】:

  • 不优雅,但我稍后会勾选的解决方案,因为它确认单独的 unnest 并不能做到这一点。
猜你喜欢
  • 2021-05-12
  • 2016-02-06
  • 2021-09-11
  • 1970-01-01
  • 1970-01-01
  • 2015-01-31
  • 2020-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多