用dplyr做一个for循环,group_by,总结,把每个变量的输出保存在一个列表中

Making a for loop with dplyr, group_by, summarize, and saving the output of each variable in a list

我想制作一个将输出保存在列表中的函数。我关心的是如何使用 dplyr group_by 和摘要指定哪一列。想象一个大数据集。请参阅下面的进一步评论。

trt <- rep(LETTERS[1:3],3)
qw <- sample(100,9)
tr <- sample(100,9)
df <- data.frame(trt,qw,tr)


  df %>%
  group_by(trt) %>%
  summarise(mean.mpg = mean(qw, na.rm = TRUE),
            sd.mpg = sd(qw, na.rm = TRUE),
            n.mpg = n())%>%
  mutate(se.mpg = sd.mpg / sqrt(n.mpg),
         lower.ci.mpg = mean.mpg - qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg,
         upper.ci.mpg = mean.mpg + qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg)
 

为什么 n[i] 不起作用?应该如何指定才能在函数中使用它?

n <- colnames(df)[2:3]
   

df %>%
   group_by(trt) %>%
   summarise(mean.mpg = mean(n[i], na.rm = TRUE),   
             sd.mpg = sd(n[i], na.rm = TRUE),
             n.mpg = n())%>%
   mutate(se.mpg = sd.mpg / sqrt(n.mpg),
          lower.ci.mpg = mean.mpg - qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg,
          upper.ci.mpg = mean.mpg + qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg)

最后我想做这个循环并将输出保存在列表中

list_Data <- list()

for (i in 2:ncol(df)){
  list_Data[[i]]<- df %>%
    group_by(trt) %>%
    summarise(mean.mpg = mean(n[i], na.rm = TRUE),
              sd.mpg = sd(n[i], na.rm = TRUE),
              n.mpg = n())%>%
    mutate(se.mpg = sd.mpg / sqrt(n.mpg),
           lower.ci.mpg = mean.mpg - qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg,
           upper.ci.mpg = mean.mpg + qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg)
}

想要的输出:

  [[1]]
    # A tibble: 3 x 7
      trt   mean.mpg sd.mpg n.mpg se.mpg lower.ci.mpg upper.ci.mpg
      <chr>    <dbl>  <dbl> <int>  <dbl>        <dbl>        <dbl>
    1 A         35.7   32.9     3   19.0        -46.0         117.
    2 B         46     37.2     3   21.5        -46.5         139.
    3 C         64.3   47.8     3   27.6        -54.4         183.


[[2]]
# A tibble: 3 x 7
  trt   mean.mpg sd.mpg n.mpg se.mpg lower.ci.mpg upper.ci.mpg
  <chr>    <dbl>  <dbl> <int>  <dbl>        <dbl>        <dbl>
1 A         57.7   40.5     3   23.4        -42.8         158.
2 B         49.3   31.0     3   17.9        -27.7         126.
3 C         32.7   34.8     3   20.1        -53.8         119.

您必须使用 rlang 包中的 sym 函数,然后使用称为 bang bang 运算符的 !! 取消引用它。在这里,因为您提供了一个字符串作为列名,所以您需要首先将它变成一个符号,该符号实际上指向数据集中的一个对象,然后您必须告诉 R 在数据集的上下文中通过 means 对其进行评估使用 !! 运算符强制评估。您可以使用 tidyverse here.

了解编程的基础知识
library(rlang)

n <- colnames(df)[2:3]
list_Data <- vector("list", length = ncol(df) - 1)

for (i in 1:(ncol(df)-1)){
  list_Data[[i]] <- df %>%
    group_by(trt) %>%
    summarise(mean.mpg = mean(!!sym(n[i]), na.rm = TRUE),
              sd.mpg = sd(!!sym(n[i]), na.rm = TRUE),
              n.mpg = n()) %>%
    mutate(se.mpg = sd.mpg / sqrt(n.mpg),
           lower.ci.mpg = mean.mpg - qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg,
           upper.ci.mpg = mean.mpg + qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg)
}


> list_Data
[[1]]
# A tibble: 3 x 7
  trt   mean.mpg sd.mpg n.mpg se.mpg lower.ci.mpg upper.ci.mpg
  <chr>    <dbl>  <dbl> <int>  <dbl>        <dbl>        <dbl>
1 A         62.7   30.6     3  17.7        -13.4         139. 
2 B         36.7   14.0     3   8.09         1.86         71.5
3 C         17.7   16.5     3   9.53       -23.3          58.7

[[2]]
# A tibble: 3 x 7
  trt   mean.mpg sd.mpg n.mpg se.mpg lower.ci.mpg upper.ci.mpg
  <chr>    <dbl>  <dbl> <int>  <dbl>        <dbl>        <dbl>
1 A           49   38.0     3   21.9        -45.4        143. 
2 B           36   21.7     3   12.5        -17.8         89.8
3 C           30   26.9     3   15.5        -36.8         96.8

一个选项是索引 .data 代词,这可以在列名存储为字符串时完成:

for (i in 1:length(n)){        # <-- Note the change from 2:ncol(df)
  list_Data[[i]]<- df %>%
    group_by(trt) %>%
    summarise(mean.mpg = mean(.data[[n[i]]], na.rm = TRUE),   # <-- .data pronoun here
              sd.mpg = sd(.data[[n[i]]], na.rm = TRUE),       #       and here
              n.mpg = n())%>%
    mutate(se.mpg = sd.mpg / sqrt(n.mpg),
           lower.ci.mpg = mean.mpg - qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg,
           upper.ci.mpg = mean.mpg + qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg)
}