R:使用dplyr突变多个列

时间:2019-09-17 13:39:58

标签: r dplyr mutate

关于堆栈溢出有很多与此有关的问题,但是我一直无法找到我的问题的解决方案。

假设我有一个带有两列的数据帧(或小记)df,例如X1X2。我有一个函数f,它接受​​输入X1X2并输出一个 vector ,例如[V1, V2]。 现在,如果输出是单例,那么我将能够写

df %>% mutate(V = f(X1,X2))

将标记为V的列添加到我的df中,条目将为f(X1,X2)。但是,我想添加两个列,V1V2。我不知道该怎么做。

当然,我可以做类似的事情

df %>% mutate(V1 = f(X1,X2)[1], V2 = f(X1,X2)[2]),

但是(我假设)涉及两次调用函数f;我有一个很大的数据集,宁愿不叫它两次。 或者,我可以做

df %>% mutate(V_list = as.list(f(X1,X2)), V1 = V_list[[1]], V2 = V_list[[2]]) %>% select(-V_list),

但这似乎是一种笨拙的方式,而我宁愿不这样做。

此外,我最终希望将其应用于group版的小标题,因此,幼稚的编写方式将为组中的每个条目重复V_list。因此,从以下意义上讲,理想的答案是“矢量化的”。 假设我已经完成df %>% group_by(var1)并拥有一个函数f,该函数将一个具有两列的数据框作为其输入-这应该被认为是“成对向量”,然后输出一个新的两列的数据框架。


以下是用于设置示例的代码。

library(dplyr)
df = tibble(var1 = c(1,1,2,2), X1 = c(1,2,3,4), X2 = c(5,6,7,8))
f = function(sub_df, var){ return( data.frame(x1 = (x1+x2)^var, x2 = (x1-x2)^var) ) }

2 个答案:

答案 0 :(得分:3)

使用tidyr 1.0.0时,您可以使用unnest_wider

修改函数,以便将输出命名为

f = function(x1,x2) c(a = x1 + x2, b = x1 - x2)

创建一个新列,该列是一个包含每一行向量的列表,然后将unnest_wider应用于此列以将向量元素拆分为自己的列。

df %>%
  mutate(new = map2(X1, X2, f)) %>%
  unnest_wider(new)
# # A tibble: 4 x 5
#    var1    X1    X2     a     b
#   <dbl> <dbl> <dbl> <dbl> <dbl>
# 1     1     1     5     6    -4
# 2     1     2     6     8    -4
# 3     2     3     7    10    -4
# 4     2     4     8    12    -4

答案 1 :(得分:2)

这可能不是理想的解决方案,但是我已经遇到了这种情况,这是我通常要做的。从函数返回分隔符分隔的字符串,并根据该分隔符separate返回该列。

f = function(x1,x2){ return( toString(c(x1+x2, x1-x2))) }

library(tidyverse)

df %>%
  mutate(new = map2_chr(X1, X2, f)) %>%
  separate(new, c("col1", "col2"), sep = ",", convert = TRUE)

# A tibble: 2 x 4
#     X1    X2  col1  col2
#  <dbl> <dbl> <int> <int>
#1     1     3     4    -2
#2     2     4     6    -2