如何从 dplyr 管道中的函数中提取多个值

Posted

技术标签:

【中文标题】如何从 dplyr 管道中的函数中提取多个值【英文标题】:How to extract several values from a function in a dplyr pipeline 【发布时间】:2021-11-15 18:34:47 【问题描述】:

有没有一种好方法来创建一个 dplyr 管道,其中 mutate 在一个步骤中从一个函数中提取几列?例如,假设您有一个这样的数据框:

 x y
 1 5
 2 3
 6 4

你有一个函数可以返回总和和乘积:

sum_and_product <- function(x, y) list(sum=x+y,product=x*y)

那么如何创建一个管道来生成原始数据帧,该数据帧由一次调用计算的 sum 和 product 列丰富?比如:

df %>% mutate_multiple(c(sum, product)=sum_and_product(x, y))

x y sum product
1 5 6   5
2 3 5   6
6 4 10  24

如果这不能通过 dplyr 管道完成,还有哪些其他替代方案?

为了让您更好地了解我在实际使用案例中想要实现的目标:我需要计算存储在单个数据框中的多个时间序列的结构变化点。当我只计算中断发生的时间时,我可以非常简单有效地做到这一点:

df %>% group_by(timeseries_id) %>% mutate(cpt = my.cpt(time, value))

但问题是,cpt 必须返回 3 个值而不仅仅是一个(更改的时间、之前的值和之后的值),这会破坏一切。当我使用循环执行此操作时,它非常缓慢(而且也很丑陋)。我想我可以编写 3 个函数,每个值提取一个,但显然这并不理想。

任何建议将不胜感激。

最好的问候, 尼古拉

【问题讨论】:

【参考方案1】:

将您的函数从 list 更改为 data.frame 即可,即

library(dplyr)
sum_and_product <- function(x, y) data.frame(sum=x+y,product=x*y)

df %>% 
 mutate(sum_and_product(x, y))
#  x y     sum     product
#1 1 5       6           5
#2 2 3       5           6
#3 6 4      10          24

【讨论】:

谢谢,这正是我想要的!【参考方案2】:

您可以将sum_and_product 的输出保存为列表,然后使用unnest_wider 从中获取不同的列。

library(dplyr)
library(tidyr)

sum_and_product <- function(x, y) list(sum=x+y,product=x*y)

df %>%
  rowwise() %>%
  mutate(z = list(sum_and_product(x, y))) %>%
  unnest_wider(z)

#      x     y   sum product
#  <int> <int> <int>   <int>
#1     1     5     6       5
#2     2     3     5       6
#3     6     4    10      24

【讨论】:

以上是关于如何从 dplyr 管道中的函数中提取多个值的主要内容,如果未能解决你的问题,请参考以下文章

dplyr 管道中嵌套函数的执行顺序

将多个列变为函数会为dplyr中的结果列内的每个组件创建一个列表

R语言基础知识|dplyr管道函数处理表格

dplyr 管道 - 如何更改原始数据框

从 Sklearn 管道中提取具有特征名称的特征重要性

作为 dplyr 管道的一部分,将中间输出分配给 temp 变量