【问题标题】:Apply a function to all columns with one columns being repeatedly used using map将函数应用于所有列,其中一列使用 map 重复使用
【发布时间】:2019-07-23 15:21:11
【问题描述】:

这是我的数据

as_tibble(data)
# A tibble: 40 x 4
   Trt        V1      V2      V3
   <fct>   <dbl>   <dbl>   <dbl>
 1 d1    0.0105  0.00940 0.0174 
 2 d1    0.0199  0.00897 0.00279
 3 d1    0.00836 0.0104  0.00816
 4 d1    0.00960 0.0131  0.00404
 5 d1    0.00527 0.0123  0.00863
 6 d1    0.0136  0.0115  0.0130 
 7 d1    0.0216  0.00591 0.0106 
 8 d1    0.00558 0.00890 0.00964
 9 d2    0.0193  0.0116  0.0199 
10 d2    0.0172  0.0165  0.0582 
# ... with 30 more rows

我想在哪里使用V*Trt 执行aov,然后执行函数f2 中给出的所有其他统计数据

f2 <- function(y, Trt){

  dt1 <- aov(y ~ Trt) %>%
    emmeans(specs = "Trt")

  dt2 <- coef(pairs(dt1)) %>%
    select(2:5)

  d3 <- contrast(dt1, dt2, adjust = "Dunnett") %>%
    summary %>%
    pull(p.value)

 return(d3)
}

当我针对 Trt 一次运行一列 V* 时,我得到了想要的结果

f2(data$V1, data$Trt)
[1] 5.450331e-01 5.936861e-01 2.302477e-02 7.882583e-15

f2(data$V2, data$Trt)
[1] 5.217088e-01 1.722111e-01 4.030167e-05 4.439782e-13

我想将f2应用于所有以V* 开头的列。这段代码出错了

map2_dfr(data %>% select_if(is.double), data$Trt, f2)
Error: Mapped vectors must have consistent lengths:
* `.x` has length 3
* `.y` has length 40

我不知道为什么map2_dfr 不能一次选择一列。有什么帮助吗?

【问题讨论】:

  • 我认为您需要传递列名(引用的)而不是值,然后使用 pastereformulate 创建公式。如果我们需要不带引号传递,那么可能需要在转换为字符后在里面创建公式

标签: r tidyverse purrr


【解决方案1】:

我会做这样的事情。首先,我加载了一些包并创建了一些与您的结构相同的随机数据。

library(dplyr, warn.conflicts = FALSE)
library(tidyr)
library(purrr)
library(emmeans)

data <- tibble::tibble(
  Trt = factor(rep(c("A", "B", "C", "D", "E"), each = 8)), 
  V1 = rnorm(40), 
  V2 = rnorm(40), 
  V3 = rnorm(40)
)

我稍微修改了f2的定义。它现在接受一个数据框和一个表示 aov 公式的字符表达式作为输入。

f2 <- function(data, aov_formula){

  dt1 <- aov(as.formula(aov_formula), data) %>%
    emmeans(specs = "Trt")

  dt2 <- coef(pairs(dt1)) %>%
    select(2:5)

  d3 <- contrast(dt1, dt2, adjust = "Dunnett") %>%
    summary %>%
    pull(p.value)

  d3
}

现在我“整理”你的数据(使用gather)如下:

data <- data %>% 
  gather("index", "y", -Trt)
data
#> # A tibble: 120 x 3
#>    Trt   index       y
#>    <fct> <chr>   <dbl>
#>  1 A     V1     0.347 
#>  2 A     V1    -0.0837
#>  3 A     V1     0.389 
#>  4 A     V1     0.0358
#>  5 A     V1    -1.45  
#>  6 A     V1     0.0621
#>  7 A     V1     0.449 
#>  8 A     V1    -1.32  
#>  9 B     V1    -0.946 
#> 10 B     V1    -0.0518
#> # ... with 110 more rows

所以现在我可以使用嵌套/映射方法将函数 f2 应用于每个 V* 变量。

data %>% 
  nest(-index) %>% 
  mutate(res = map(data, f2, aov_formula = "y ~ Trt")) %>% 
  unnest(res)
#> # A tibble: 12 x 2
#>    index   res
#>    <chr> <dbl>
#>  1 V1    0.996
#>  2 V1    0.986
#>  3 V1    0.781
#>  4 V1    0.721
#>  5 V2    1.000
#>  6 V2    0.798
#>  7 V2    0.965
#>  8 V2    1.000
#>  9 V3    0.949
#> 10 V3    0.551
#> 11 V3    0.546
#> 12 V3    0.670

reprex package (v0.3.0) 于 2019 年 7 月 23 日创建

如果您不喜欢生成的数据框的形状,可以使用收集和散布对其进行整形。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-24
    • 2014-05-03
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    相关资源
    最近更新 更多