【问题标题】:R- Referencing different dataframes in a loopR-在循环中引用不同的数据帧
【发布时间】:2017-10-27 18:41:00
【问题描述】:

我是 R 的新手,所以如果我认为这是完全错误的,请随时告诉我。我有一系列关于发电厂的导入数据框,每年一个(Plant1987、Plant1988 等),我试图最终将它们组合成一个数据框。在这样做之前,我想为每个数据框添加一个“年份”变量。我可以为每个单独的数据框执行此操作,但希望将其形式化并一步完成。我知道如何在 stata 中做到这一点,但我在这里苦苦挣扎。

我的想法是这样的:

for (y in 1987:2008) {
     paste("Plant",y,sep="")$year <- y
}

这不起作用,因为 paste 显然不是正确的功能。有没有一种聪明、快速的方法来做到这一点?谢谢

【问题讨论】:

  • Store your data.frames in a list;不要创建一堆名称中包含数据的变量。然后您可以在该列表上应用函数。 paste() 创建字符向量。字符向量与名称/符号不同。
  • @MrFlick 你能帮我多想想这样的功能会是什么样子吗?我了解将函数应用于列表中的数据框的概念,但我不明白如何引用数据框名称的一部分来创建新变量

标签: r for-loop dataframe


【解决方案1】:

试试这个..

year=seq(1987,2008,by=1)
list_object_names = sprintf("Plant%s", 1987:2008)

list_DataFrame = lapply(list_object_names, get)

for (i in 1:length(list_DataFrame ) ){
    list_DataFrame[[i]][,'Year']=year[i]
}

【讨论】:

  • 不错,我喜欢。
  • 非常感谢。我的朋友也给了我一个解决方案,我稍后会发布。
【解决方案2】:

这里有一些代码可以给你一些想法。我以mtcars 数据框为例,创建了一个包含三个数据框的列表。之后,我使用两种解决方案将年份(2000 年到 2002 年)添加到每个数据框。您需要修改数据的代码。

# Load the mtcars data frame
data(mtcars)

# Create a list with three data frames
ex_list <- list(mtcars, mtcars, mtcars)

# Create a list with three years: 2000 to 2002
year_list <- 2000:2002

解决方案 1:使用基础 R 中的 lapply

ex_list2 <- lapply(1:3, function(i) {

  dt <- ex_list[[i]]

  dt[["Year"]] <- year_list[[i]]

  return(dt)
})

解决方案 2:使用 purrr 中的 map2

library(purrr)    

ex_list3 <- map2(ex_list, year_list, .f = function(dt, year){

  dt$Year <- year

  return(dt)
})

ex_list2ex_list3 是最终输出。

【讨论】:

    【解决方案3】:

    假设你有 data.frames

    Plant1987 <- data.frame(plantID=1:4, x=rnorm(4))
    Plant1988 <- data.frame(plantID=1:4, x=rnorm(4))
    Plant1989 <- data.frame(plantID=1:4, x=rnorm(4))
    

    您可以在每个字段中添加一个$year

    year <- 1987:1989
    for(yeari in year) {
      eval(parse(text=paste0("Plant",yeari,"$year<-",yeari)))
    }
    
    Plant1987
    #   plantID           x year
    # 1       1  0.67724230 1987
    # 2       2 -1.74773250 1987
    # 3       3  0.67982621 1987
    # 4       4  0.04731677 1987
    # ...etc for other years...
    

    ...或者将它们绑定到一个data.frame中

    df <- Plant1987
    for(yeari in year[-1]) {
      df <- rbind(df, eval(parse(text=paste0("Plant",yeari))))
    }
    
    df
    #    plantID            x year
    # 1        1  0.677242300 1987
    # 2        2 -1.747732498 1987
    # 3        3  0.679826213 1987
    # 4        4  0.047316768 1987
    # 5        1  1.043299473 1988
    # 6        2  0.003758675 1988
    # 7        3  0.601255190 1988
    # 8        4  0.904374498 1988
    # 9        1  0.082030356 1989
    # 10       2 -1.409670456 1989
    # 11       3 -0.064881722 1989
    # 12       4  1.312507736 1989
    

    ...或在列表中作为

    itsalist <- list()
    for(yeari in year) {
      eval(parse(text=paste0("itsalist$Plant",yeari,"<-Plant",yeari)))
    }
    
    itsalist
    # $Plant1987
    #   plantID           x year
    # 1       1  0.67724230 1987
    # 2       2 -1.74773250 1987
    # 3       3  0.67982621 1987
    # 4       4  0.04731677 1987
    # 
    # $Plant1988
    #   plantID           x year
    # 1       1 1.043299473 1988
    # 2       2 0.003758675 1988
    # 3       3 0.601255190 1988
    # 4       4 0.904374498 1988
    # 
    # $Plant1989
    #   plantID           x year
    # 1       1  0.08203036 1989
    # 2       2 -1.40967046 1989
    # 3       3 -0.06488172 1989
    # 4       4  1.31250774 1989
    

    【讨论】:

    • 这不是我的建议。如果数据在xx&lt;-list(Plant1987, Plant1988, Plant1989 ) 之类的列表中,那么您可以使用Map(function(d,y) {d$year&lt;-y; d}, xx, 1987:1989)。最好avoid eval-parse
    • @MrFlick 感谢您的提示和参考!一直在学习。
    猜你喜欢
    • 1970-01-01
    • 2018-01-18
    • 2019-07-29
    • 2017-10-04
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    相关资源
    最近更新 更多