dplyr::mutate以添加多个值

dplyr::mutate以添加多个值,r,dplyr,R,Dplyr,关于这个问题,已经有几个问题了,至少有一个相关的SO问题,但没有一个完全涵盖了我的问题——我想 这或多或少是我想要的,但有一个特殊的案例答案(tidyr::separate)对我来说并不适用 (“使用返回多个值/列的函数进行汇总或变异”)表示“使用do()” 这是我的用例:我想计算精确的二项式置信区间 dd <- data.frame(x=c(3,4),n=c(10,11)) get_binCI <- function(x,n) { rbind(setNames(c(bi

关于这个问题,已经有几个问题了,至少有一个相关的SO问题,但没有一个完全涵盖了我的问题——我想

  • 这或多或少是我想要的,但有一个特殊的案例答案(
    tidyr::separate
    )对我来说并不适用
  • (“使用返回多个值/列的函数进行汇总或变异”)表示“使用
    do()
这是我的用例:我想计算精确的二项式置信区间

dd <- data.frame(x=c(3,4),n=c(10,11))
get_binCI <- function(x,n) {
    rbind(setNames(c(binom.test(x,n)$conf.int),c("lwr","upr")))
}
with(dd[1,],get_binCI(x,n))
##             lwr       upr
## [1,] 0.06673951 0.6524529

下面是一个使用
data.table
包的快速解决方案

首先,对函数进行一点更改

get_binCI <- function(x,n) as.list(setNames(binom.test(x,n)$conf.int, c("lwr", "upr")))
这使用了一个“标准”的dplyr工作流,但正如@BenBolker在评论中指出的那样,它需要调用
get\u binCI
两次:

dd %>% group_by(x,n) %>%
  mutate(lwr=get_binCI(x,n)[1],
         upr=get_binCI(x,n)[2])

  x  n        lwr       upr
1 3 10 0.06673951 0.6524529
2 4 11 0.10926344 0.6920953

还有另一种变体,尽管我认为我们在这里都是在吹毛求疵

> dd <- data.frame(x=c(3,4),n=c(10,11))
> get_binCI <- function(x,n) {
+   as_data_frame(setNames(as.list(binom.test(x,n)$conf.int),c("lwr","upr")))
+ }
> 
> dd %>% 
+   group_by(x,n) %>%
+   do(get_binCI(.$x,.$n))
Source: local data frame [2 x 4]
Groups: x, n

  x  n        lwr       upr
1 3 10 0.06673951 0.6524529
2 4 11 0.10926344 0.6920953
>dd get\u binCI
>dd%>%
+(x,n)%>%
+do(获取比尼(x美元,n美元))
来源:本地数据帧[2 x 4]
组:x,n
x n lwr不饱和聚酯树脂
1 3 10 0.06673951 0.6524529
2 4 11 0.10926344 0.6920953
就我个人而言,如果我们只考虑可读性,我认为这更可取:

foo  <- function(x,n){
    bi <- binom.test(x,n)$conf.int
    data_frame(lwr = bi[1],
               upr = bi[2])
}

dd %>% 
    group_by(x,n) %>%
    do(foo(.$x,.$n))
foo%
do(foo(.$x,.$n))

…但现在我们真的在挑拨离间。

这里有一些使用
行方式和
嵌套的可能性

library("dplyr")
library("tidyr")
重复x/n组合的数据帧,非常有趣

dd <- data.frame(x=c(3, 4, 3), n=c(10, 11, 10))
使用
rowwise
保留所有行,但删除
x
n
,除非使用
cbind(.
(就像Ben在他的OP中那样)将它们放回原处


最后,对于dplyr来说,这似乎是一个尚未解决的问题(截至2017年10月5日);请参阅;如果实现了类似的问题,那么这将是最简单的方法!

另一个选项可能是使用
purr::map
函数系列

如果在
get\u binCI
函数中将
rbind
替换为
dplyr::bind\u rows

库(tidyverse)
dd%unnest()
#>x n lwr不饱和聚酯树脂
#> 1 3 10 0.06673951 0.6524529
#> 2 4 11 0.10926344 0.6920953
purrr::map2\u dfr
dplyr::bind\u cols

dd%>%bind\u cols(map2\u dfr(.$x,.$n,get\u binCI))
#>x n lwr不饱和聚酯树脂
#> 1 3 10 0.06673951 0.6524529
#> 2 4 11 0.10926344 0.6920953
老问题(有很多好答案),但这是tidyverse的一个很好的用例,它处理测试和建模对象(例如
binom.test
lm
)的整理输出

它比其他方法更冗长,但我认为它符合您对更具表现力的方法的渴望

这个过程是:

  • 定义要运行
    binom.test
    的组(在本例中,这些组由
    x
    n
    定义)并
    嵌套它们,为每个组创建单独的data.frames(在完整的data.frames内)
  • map
    binom.test
  • 调用每组的
    x
    n
  • tidy
    每组的
    binom.test
    输出(这就是扫帚的作用)
  • unest
    将整理好的测试输出data.frames转换为完整的data.frames
  • 现在,您将看到一个data.frame,其中每一行包含
    x
    n
    值,与相应的
    binom.test
    的所有输出相结合,整齐地格式化为每一位输出信息(点估计、上/下形态、p值等)的单独列

    库(tidyverse)
    图书馆(扫帚)
    dd%
    (x,n)%>%
    嵌套()%>%
    变异(测试=映射(数据,~tidy(binom.test(x,n)))%>%
    unnest(测试)
    #>#tibble:2 x 11
    #>#组:x,n[2]
    #>x n数据估计统计p.值参数conf.low conf.high
    #>                               
    #>1 3 10 2 4 11#…还有两个变量:方法、备选方案
    
    从这里,您只需稍加操作,选择所需的输出变量并重命名它们,即可获得精确的所需格式:

    dd%>%
    (x,n)%>%
    嵌套()%>%
    变异(测试=映射(数据,~tidy(binom.test(x,n)))%>%
    未测试(测试)%>%
    重命名(lwr=conf.low,upr=conf.high)%>%
    选择(x、n、lwr、upr)
    #>#A tibble:2 x 4
    #>#组:x,n[2]
    #>x n lwr不饱和聚酯树脂
    #>       
    #> 1     3    10 0.0667 0.652
    #> 2     4    11 0.109  0.692
    
    如前所述,它是冗长的。比(例如)@joran的优美简洁更为冗长

    dd%>%
    (x,n)%>%
    do(foo(.$x,.$n))
    

    然而,扫帚方法的好处是,您不需要定义函数
    foo
    (或
    get_binCI
    )。它是完全独立的,并且在我看来更具表现力和灵活性。

    您是否已经决定特别使用
    dplyr
    ?使用,
    数据。table
    您可以快速执行
    setDT(dd)[,as.list(get_binCI(x,n)),by=(x,n)]
    虽然我的读心技能不允许我确定你所说的“表达方式”到底是什么意思……这当然是好的。我希望得到一个
    dplyr
    答案(尽管如果我上面的解决方案是最好的,我不会感到惊讶).我并不反对
    数据.table
    ,但我更喜欢
    dplyr
    ,而且——大多数情况下——我仍然在花大量的脑力来处理它,我真的不想添加一套全新的语法(也不想把它强加给我的学生和同事)现在。但如果你这样回答,我会投赞成票,这是很有用的。大家好,希望把这个问题提出来;现在有更好的方法来做嵌套吗?我正在尝试,但还没有得到。@Aaron,我尝试过使用
    unnest
    ,它也使用
    map2
    ,你可能会感兴趣是的,这是一个解决方案,但它的丑陋之处在于s必须调用两次
    get\u binCI()
    。有点像是在ey中
    library("dplyr")
    library("tidyr")
    
    dd <- data.frame(x=c(3, 4, 3), n=c(10, 11, 10))
    
    get_binCI_df <- function(x,n) {
      binom.test(x, n)$conf.int %>% 
        setNames(c("lwr", "upr")) %>% 
        as.list() %>% as.data.frame()
    }
    
    dd %>% group_by(x,n) %>% do(get_binCI_df(.$x,.$n))
    # # A tibble: 2 x 4
    # # Groups:   x, n [2]
    #       x     n       lwr       upr
    #   <dbl> <dbl>     <dbl>     <dbl>
    # 1     3    10 0.1181172 0.8818828
    # 2     4    11 0.1092634 0.6920953
    
    dd %>% rowwise() %>% do(cbind(., get_binCI_df(.$x,.$n)))
    # Source: local data frame [3 x 4]
    # Groups: <by row>
    #   
    # # A tibble: 3 x 4
    #       x     n        lwr       upr
    # * <dbl> <dbl>      <dbl>     <dbl>
    # 1     3    10 0.06673951 0.6524529
    # 2     4    11 0.10926344 0.6920953
    # 3     3    10 0.06673951 0.6524529
    
    dd %>% rowwise() %>% mutate(ci=list(get_binCI_df(x, n))) %>% unnest()
    # # A tibble: 3 x 4
    #       x     n        lwr       upr
    #   <dbl> <dbl>      <dbl>     <dbl>
    # 1     3    10 0.06673951 0.6524529
    # 2     4    11 0.10926344 0.6920953
    # 3     3    10 0.06673951 0.6524529