for循环遍历数据帧列表

时间:2018-03-31 03:36:19

标签: r loops for-loop

我正在尝试编写一个首先检查它是否是数据帧的for循环。如果它是数据框,则迭代数据帧并计算平均值,然后创建具有平均值的新列。这是一个例子:

df1 <- data.frame(
  Number = c(45,62,27,34,37,55,40))
df2 <- data.frame(
  Number = c(15,20,32,21,17,18,13))
df3 <- data.frame(
  Number = c(12,32,22,14,16,21,30))

L <- list(df1,df2,df3)

for(i in L){if(is.data.frame(i)){
  i$Average <- mean(i)
}
}

和df1之后的结果示例是:

 Number  Average
1     45 42.85714
2     62 42.85714
3     27 42.85714
4     34 42.85714
5     37 42.85714
6     55 42.85714
7     40 42.85714

谢谢!

3 个答案:

答案 0 :(得分:2)

如果我们需要使用新值更新原始data.frame对象,请使用assign

nm1 <- paste0("df", 1:3)
for(i in seq_along(L)) {
    assign(nm1[i], `[<-`(L[[i]], "Average", value = mean(L[[i]]$Number)))
 }   

df1
#  Number  Average
#1     45 42.85714
#2     62 42.85714
#3     27 42.85714
#4     34 42.85714
#5     37 42.85714
#6     55 42.85714
#7     40 42.85714

关于为什么OP的循环不起作用,

for(i in L) print(i)

返回list的值,而不是对象的名称。所以,我们不能分配i$Average <-list元素没有名称。另外,mean适用于vector。它可以直接应用于data.frame

mean(L[[1]])
#[1] NA
  

警告消息:在mean.default(L [[1]])中:参数不是数字或   逻辑:返回NA

mean(L[[1]]$Number)
#[1] 42.85714

for循环中,这意味着我们获得了NAs

for(i in L) mean(i)
#  Warning messages:
#1: In mean.default(i) : argument is not numeric or logical: returning NA
#2: In mean.default(i) : argument is not numeric or logical: returning NA
#3: In mean.default(i) : argument is not numeric or logical: returning NA

一旦我们提取专栏&#39;数字&#39;,mean作品

for(i in L) print(mean(i$Number))
#[1] 42.85714
#[1] 19.42857
#[1] 21

但是,更容易将其保留在list中并更新list中的数据集。使用lapply创建一列“平均值”&#39;循环遍历list并获取&#39;数字&#39;

mean
lapply(L, transform, Average = mean(Number))

tidyverse

library(tidyverse)
L %>%
   map(~ .x %>%
            mutate(Average = mean(Number)))

答案 1 :(得分:1)

您可以使用purrr::map执行此操作:

require(purrr)

L %>%
  map(
    .f =
      ~ .x %>%
      {
        if (is.data.frame(.)) {
          mutate(., Average = mean(Number))
        }
      }
  )

# [[1]]
#   Number  Average
# 1     45 42.85714
# 2     62 42.85714
# 3     27 42.85714
# 4     34 42.85714
# 5     37 42.85714
# 6     55 42.85714
# 7     40 42.85714
# 
# [[2]]
#   Number  Average
# 1     15 19.42857
# 2     20 19.42857
# 3     32 19.42857
# 4     21 19.42857
# 5     17 19.42857
# 6     18 19.42857
# 7     13 19.42857

# [[3]]
#   Number Average
# 1     12      21
# 2     32      21
# 3     22      21
# 4     14      21
# 5     16      21
# 6     21      21
# 7     30      21

答案 2 :(得分:1)

i只是用于控制for循环的临时对象。要对存储在循环外L中的数据帧进行更改,请尝试按照这样的数字进行索引。

df1 <- data.frame(Number = c(45,62,27,34,37,55,40))
df2 <- data.frame(Number = c(15,20,32,21,17,18,13))
df3 <- data.frame(Number = c(12,32,22,14,16,21,30))

L <- list(df1,df2,df3)

for(i in 1:length(L)){if(is.data.frame(L[[i]])){

## Requires explicitly extracting the values in 
## L[[i]] by name.  So could be problematic if you actually
## have many columns in your dataframes.  
L[[i]]$Average <- mean(L[[i]]$Number)
}
}