【问题标题】:Using nested for loops to create a data frame in R使用嵌套的 for 循环在 R 中创建数据框
【发布时间】:2016-05-09 07:41:02
【问题描述】:

我正在寻找一种方法来使用两个 for 循环在 R 中创建一个特定的数据框。我开始使用一个函数,但在使用它时遇到了一些困难。第一个 for 循环将遍历数据帧列表的名称,第二个 for 循环将遍历每个数据帧的列并返回平均值。然后,输出将返回一个数据帧,其中每一行都包含其中一个数据帧的列的平均值。这是一些虚拟数据:

first<- data.frame(b = factor(c("Hi", "Hi","Hi","Hi")), y = c(8, 3, 9, 9),
               z = c(1, 1, 1, 2))
second<- data.frame(b = factor(c("Med", "Med", "Med", "Med")),y = c(3, 2, 6, 5),
                z = c(1, 11, 4, 3))

third<- list(first,second)
fourth<- c("first","second")
names(third)<- c(fourth)
fifth<- c("y","z")

这是我正在处理的函数:

testr<- function(arg1,arg2){
  a<- list()
  for(i in 1:length(arg1)){
   b<- (third[[arg1[i]]])
    for(j in 1:length(arg2)){
      c<- mean(b[[arg2[[j]]]])
      a[[j]]<-c
    }
  }
  df<- do.call("cbind",a)
  df<-as.data.frame(df)
  df$name<- arg1
  return(df)
}

我的目标是这样的结果:

testr(fourth,fifth)

    V1   V2  name
1 7.25 1.25 first
2    4 4.75 second

但是我得到了这个:

testr(fourth,fifth)

 Error in `$<-.data.frame`(`*tmp*`, "name", value = c("first", "second" : 
  replacement has 2 rows, data has 1 

任何帮助将不胜感激!

【问题讨论】:

  • aggregate(. ~ b, data = rbind(first, second), mean) 提供类似于您所需输出的内容。但也许我不明白你的问题的全部复杂性。

标签: r function loops for-loop arguments


【解决方案1】:

假设您有许多这样的数据框firstsecond 以及这样的数据框列表如下,您可以使用dplyr 得到所需的结果,如下所示:

library(dplyr)
l <- list(first, second)
df <- do.call(rbind, l)
df %>% group_by(b) %>% summarise_each(funs(mean))

输出是:

Source: local data frame [2 x 3]

       b     y     z
  (fctr) (dbl) (dbl)
1     Hi  7.25  1.25
2    Med  4.00  4.75

【讨论】:

    【解决方案2】:

    我的建议...让我们一起避免 for 循环。看起来您只需要两列的平均值和 data.frame 的名称。

    通过dplyrdata.table 学习一些技巧,使这种类型的总结变得微不足道。

    library(dplyr)
    third %>% 
      bind_rows(.id = "name") %>% 
      group_by(name) %>% 
      summarize(
        V1 = mean(y), 
        V2 = mean(z))
    
    # Source: local data frame [2 x 3]
    #
    #     name    V1    V2
    #    (chr) (dbl) (dbl)
    # 1  first  7.25  1.25
    # 2 second  4.00  4.75
    
    
    library(data.table)
    dt <- rbindlist(third)
    dt[,list(V1 = mean(y),V2 = mean(z)),by = b]
    #      b   V1   V2
    # 1:  Hi 7.25 1.25
    # 2: Med 4.00 4.75
    
    # or as David points out.
    dt[, lapply(.SD, mean), by = b]
    #      b    y    z
    # 1:  Hi 7.25 1.25
    # 2: Med 4.00 4.75
    

    【讨论】:

    • 你可以做dt[, lapply(.SD, mean), by = b]
    猜你喜欢
    • 1970-01-01
    • 2018-05-31
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 2021-01-13
    相关资源
    最近更新 更多