【问题标题】:R: Split-Apply-Combine... Apply Functions via Aggregate to Row-Bound Data Frames Subset by ClassR:拆分-应用-组合...通过聚合将函数应用到按类划分的行绑定数据帧子集
【发布时间】:2013-07-26 21:40:56
【问题描述】:

更新:我的 NOAA GHCN-Daily 气象站数据功能已被清理并合并到 rnoaa 包中,可在 CRAN 或此处获取: https://github.com/ropensci/rnoaa

我正在设计一个 R 函数来计算由多个数据帧组成的数据集的统计数据。简而言之,我想根据包含名称的参考数据框按类提取数据框。然后,我想将统计函数应用于每个给定日期列出的指标的值。实际上,我想调用并覆盖一个数据框列表,以计算每个唯一日期和值不为 NA 的指标的值向量上的函数。

使用“by”函数,基于类变量将数据帧从文件中迭代地读入工作区。导入给定类的文件后,我想 rbind() 该类的数据框和一个年份范围内的每个用户定义的指标。然后,我想将用户提供的统计函数串联应用于与年、月和日的给定值相对应的类中的每个指标(即,7 月 1 日的平均 [函数] 低温 [类], 1990 [日期] 报告给定区域 [类] 内的所有位置 [数据框]。我希望最终结果是新的数据框,其中包含区域内每个日期的值以及应用的每个指标和统计函数的年份范围。我非常接近使用聚合()函数得到这个结果,但是我无法从聚合函数中获得合理的结果,该函数目前正在为除平均温度以外的大多数函数输出 NA 和 NaN。任何建议都会很多感谢!这是我迄今为止的代码:

# Example parameters
w <- c("mean","sd","scale")             # Statistical functions to apply
x <- "C:/Data/"                         # Folder location of CSV files
y <- c("MaxTemp","AvgTemp","MinTemp")   # Metrics to subset the data
z <- c(1970:2000)                       # Year range to subset the data

 CSVstnClass  <- data.frame(CSVstations,CSVclasses)

  by(CSVstnClass, CSVstnClass[,2], function(a){                        # Station list by class
  suppressWarnings(assign(paste(a[,2]),paste(a[,1]),envir=.GlobalEnv))
    apply(a, 1, function(b){                                           # Data frame list, row-wise
      classData   <- data.frame()
      sapply(y, function(d){                                           # Element list
        CSV_DF    <- read.csv(paste(x,b[2],"/",b[1],".csv",sep=""))    # Read in CSV files as data frames
        CSV_DF1   <- CSV_DF[!is.na("Value")]
        CSV_DF2   <- CSV_DF1[which(CSV_DF1$Year %in% z & CSV_DF1$Element == d),]
        assign(paste(b[2],"_",d,sep=""),CSV_DF2,envir=.GlobalEnv)

        if(nrow(CSV_DF2) > 0){                                         # Remove empty data frames
          classData <<- rbind(classData,CSV_DF2)                       # Bind all data frames by row for a class and element
          assign(paste(b[2],"_",d,"_bound",sep=""),classData,envir=.GlobalEnv)

          sapply(w, function(g){                                       # Function list
                                                                       # Aggregate results of bound data frame for each unique date
            dataFunc <- aggregate(Value~Year+Month+Day+Element,data=classData,FUN=g,na.action=na.pass)
            assign(paste(b[2],"_",d,"_",g,sep=""),dataFunc,envir=.GlobalEnv)
            })
        }
        })
      })
    })

我想我已经很接近了,但我不确定 rbind() 是否正常执行,也不确定为什么 aggregate() 函数会为这么多指标输出 NA 和 NaN。我担心数据框没有绑定在一起,或者某些统计函数没有很好地处理缺失值。提前感谢您提供的任何建议。

干杯,

亚当

【问题讨论】:

  • 这个“ DFbound
  • &lt;&lt;- 是一个全局分配。这是一个合法但非常不鼓励的功能。
  • 没见过
  • 实际上,这并不完全准确。从 CRAN 上 An Introduction to R 的第 47 页,特殊赋值运算符 因此,它将找到一个空列表,我已经创建了几个环境。嵌套列表(例如 x$x$x)会变得更奇怪。

标签: r user-defined-functions nested-loops nested-lists rbind


【解决方案1】:

您以一种很难调试的方式解决了这个问题。我建议您切换一些东西,这样您就可以更轻松地检查每个步骤。 (使用信息变量名也有帮助!)代码不太可能按原样工作,但迭代工作应该更容易,在继续下一步之前检查每个步骤是否成功。

paths <- dir("C:/Data/", pattern = "\\.csv$")

# Read in CSV files as data frames
raw <- lapply(paths, read.csv, str)

# Extract needed rows
filter_metrics <- c("MaxTemp", "AvgTemp", "MinTemp")
filter_years <- 1970:2000
filtered <- lapply(raw, subset, 
  !is.na(Value) & Year %in% filter_years & Element %in% filter_metrics)

# Drop any empty data frames
rows <- vapply(filtered, nrow, integer(1))
filtered <- filtered[rows > 0]

# Compute aggregates
my_aggregate <- function(df, fun) {
  aggregate(Value ~ Year + Month + Day + Element, data = df, FUN = fun, 
    na.action = na.pass)
}    
means <- lapply(filtered, my_aggregate, mean)
sds <- lapply(filtered, my_aggregate, sd)
scales <- lapply(filtered, my_aggregate, scale)

【讨论】:

  • Hadley,非常感谢您对此给予关注。我将根据上述建议进行工作,并在进行更多调试后发布更新。再次感谢您!
  • 更新:我的 NOAA GHCN-Daily 气象站数据功能已被清理并合并到 rnoaa 包中,可在 CRAN 或此处获取:github.com/ropensci/rnoaa
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-23
  • 1970-01-01
  • 2015-10-03
  • 2012-12-20
  • 1970-01-01
  • 2020-06-12
相关资源
最近更新 更多