【问题标题】:Looping same function over data frames in R在R中的数据帧上循环相同的函数
【发布时间】:2021-11-07 05:44:38
【问题描述】:

我是 R 新手。我想通过多个数据帧重新编码同一个变量。但我不断收到错误。请参阅以下 3 个小数据帧的示例。我想在 3 个名为 Q2_nom 的 dfs 中的每一个中创建一个新变量,如果 Q2 大于或小于平均值(Q2),则将其重新编码为“1”或“0”。请在下面查看我的代码。

df1:

Q1 <- c('ABC','DEF','GHI', 'DEF','JKL','XYZ')
Q2 <- c(21000, 23400, 26800, 26000, 20400, 30800)
df1 <- data.frame(Q1, Q2)

df2:

Q1 <- c('DEF','JKL','XYZ', 'ABC', 'MNO', 'PQR')
Q2 <- c(30100, 20200, 15800, 21000, 23400, 26800)
df2 <- data.frame(Q1, Q2)

df3:

Q1 <- c('ABC','DEF','GHI', 'XYZ', 'MNO', 'PQR')
Q2 <- c(17800, 23060, 13080, 27000, 22400, 26500)
df3 <- data.frame(Q1, Q2)

a <- c("Q1", "Q2", "Q3")

for (i in a) {
  newname <- paste(i)
  newname$Q2_mean_nom <- ifelse(newmame$Q2 > mean(newname$Q2, na.rm = TRUE), "1", "0")
}

我注意到在执行上述操作时,newname 不是 df,因此平均值不会运行。有没有办法让循环将 newname 识别为 df?

我尝试使用列表,但也没有用。

newlist <- c(df1, df2, df3)

for (i in 1:length(newlist)) {
  newlist[[i]]$Q2_mean_nom <- ifelse(newlist[[i]]$Q2 > mean(newlist[[i]]$Q2, na.rm = TRUE),
"1", "0")
 }

请帮忙。非常感谢!

【问题讨论】:

    标签: r loops


    【解决方案1】:

    使用你漂亮的基础 R 方法,稍作修改就可以了:

    # list instead of vector:
    newlist <- list(df1, df2, df3)
    # someone told me once `seq_along`is more stable
    for (i in seq_along(newlist)) {
      newlist[[i]]$Q2_mean_nom <- ifelse(newlist[[i]]$Q2 > mean(newlist[[i]]$Q2, na.rm = TRUE), "1", "0")
    }
    

    编辑(见 cmets):

    # df1:
    Q1 <- c('ABC','DEF','GHI', 'DEF','JKL','XYZ')
    Q2 <- c(21000, 23400, 26800, 26000, 20400, 30800)
    df1 <- data.frame(Q1, Q2)
    # df2:
    Q1 <- c('DEF','JKL','XYZ', 'ABC', 'MNO', 'PQR')
    Q2 <- c(30100, 20200, 15800, 21000, 23400, 26800)
    df2 <- data.frame(Q1, Q2)
    # df3:
    Q1 <- c('ABC','DEF','GHI', 'XYZ', 'MNO', 'PQR')
    Q2 <- c(17800, 23060, 13080, 27000, 22400, 26500)
    df3 <- data.frame(Q1, Q2)
    
    # list instead of vector:
    newlist <- list(df1, df2, df3)
    # someone told me once `seq_along`is more stable
    for (i in seq_along(newlist)) {
      newlist[[i]]$Q2_mean_nom <- ifelse(newlist[[i]]$Q2 > mean(newlist[[i]]$Q2, na.rm = TRUE), "1", "0")
    }
    
    newlist # displays output, see next chunk.
    
    # output:
    #> [[1]]
    #>    Q1    Q2 Q2_mean_nom
    #> 1 ABC 21000           0
    #> 2 DEF 23400           0
    #> 3 GHI 26800           1
    #> 4 DEF 26000           1
    #> 5 JKL 20400           0
    #> 6 XYZ 30800           1
    #> 
    #> [[2]]
    #>    Q1    Q2 Q2_mean_nom
    #> 1 DEF 30100           1
    #> 2 JKL 20200           0
    #> 3 XYZ 15800           0
    #> 4 ABC 21000           0
    #> 5 MNO 23400           1
    #> 6 PQR 26800           1
    #> 
    #> [[3]]
    #>    Q1    Q2 Q2_mean_nom
    #> 1 ABC 17800           0
    #> 2 DEF 23060           1
    #> 3 GHI 13080           0
    #> 4 XYZ 27000           1
    #> 5 MNO 22400           1
    #> 6 PQR 26500           1
    

    由 reprex 包 (v2.0.1) 于 2021-09-11 创建

    【讨论】:

    • 谢谢!我试过但得到以下错误:错误:$ operator is invalid for atomic vectors 有什么想法吗?
    • 我认为你犯了一个小错误。我用完整的代码扩展了我的答案。尝试复制它。
    • 完成。您不需要复制newline 后面的所有内容,从那里显示输出。请从上到下执行完整代码以允许覆盖。在一个全新的干净的 R 会话中复制代码可能是个好主意。
    • 谢谢!有用!然后我应该如何从列表 newlist 中提取 dfs 作为单独的 dfs?
    • 如果您喜欢我的回答,您可以投票/接受!如果您需要特定的 df,这将是一种相当奇怪的方式来获得您想要的东西:DF1 &lt;- as.data.frame(newlist[1])。有关更多信息,请参见例如stackoverflow.com/questions/66416523/…你现在知道如何处理它们了,为什么要提取单个的?
    【解决方案2】:

    我们可以使用来自purrr 包的map

    1. 将您的 df 保存在 df 列表中
    2. 然后在每个 df 上使用 map 进行迭代,然后
    3. mutate 带有您的 ifelse 条件的新列
    library(purrr)
    library(dplyr)
    list_df %>% 
        map(~mutate(., Q2_mean_nom = ifelse(Q2 > mean(Q2, na.rm = TRUE), 1, 0)))
    
    [[1]]
       Q1    Q2 Q2_mean_nom
    1 ABC 21000           0
    2 DEF 23400           0
    3 GHI 26800           1
    4 DEF 26000           1
    5 JKL 20400           0
    6 XYZ 30800           1
    
    [[2]]
       Q1    Q2 Q2_mean_nom
    1 DEF 30100           1
    2 JKL 20200           0
    3 XYZ 15800           0
    4 ABC 21000           0
    5 MNO 23400           1
    6 PQR 26800           1
    
    [[3]]
       Q1    Q2 Q2_mean_nom
    1 ABC 17800           0
    2 DEF 23060           1
    3 GHI 13080           0
    4 XYZ 27000           1
    5 MNO 22400           1
    6 PQR 26500           1
    

    【讨论】:

    • 谢谢!我试过了,但出现以下错误: UseMethod("mutate_") 中的错误:没有适用于 'mutate_' 的方法应用于“字符”类的对象有什么想法吗?
    【解决方案3】:

    使用mgetpaste0 获取命名列表中的数据。使用lapply 在每个数据帧中创建一个新列,使用list2env 将这些更改反映在各个数据帧中。

    在基础 R 中,您可以这样做

    list_data <- mget(paste0('df', 1:3))
    list_data <- lapply(list_data, function(x) 
                transform(x, Q2_mean_nom = as.integer(Q2 > mean(Q2, na.rm = TRUE))))
    
    list2env(list_data, .GlobalEnv)
    
    df1
    #   Q1    Q2 Q2_mean_nom
    #1 ABC 21000           0
    #2 DEF 23400           0
    #3 GHI 26800           1
    #4 DEF 26000           1
    #5 JKL 20400           0
    #6 XYZ 30800           1
    
    df2
    #   Q1    Q2 Q2_mean_nom
    #1 DEF 30100           1
    #2 JKL 20200           0
    #3 XYZ 15800           0
    #4 ABC 21000           0
    #5 MNO 23400           1
    #6 PQR 26800           1
    
    df3
    #   Q1    Q2 Q2_mean_nom
    #1 ABC 17800           0
    #2 DEF 23060           1
    #3 GHI 13080           0
    #4 XYZ 27000           1
    #5 MNO 22400           1
    #6 PQR 26500           1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-19
      • 1970-01-01
      • 2021-09-20
      • 2017-10-27
      • 2019-07-29
      • 2019-11-13
      • 2016-08-24
      • 2019-11-15
      相关资源
      最近更新 更多