【问题标题】:Averaging daily data over many years to replace NA values in R多年平均每日数据以替换 R 中的 NA 值
【发布时间】:2013-03-09 01:28:24
【问题描述】:

我有一个名为 daily 的数据框,如下所示:

      daily[1:10,]
         Climate_Division    Date      Precipitation
      1                 1 1948-07-01     0.2100000
      2                 1 1948-07-02     0.7000000
      3                 1 1948-07-03     0.1900000
      4                 1 1948-07-04     0.1033333
      5                 1 1948-07-05     0.1982895
      6                 1 1948-07-06     0.1433333
      7                 1 1948-07-07            NA
      8                 1 1948-07-08            NA
      9                 1 1948-07-09            NA
      10                1 1948-07-10            NA

我想要实现的目标是平均所有年份(1948-1995 年)的所有日期值,以替换特定日期出现的 NA 值。例如,由于第 7 行的 NA 为 1948 年 7 月 7 日,我将平均 1948 年至 1995 年的所有 7 月 7 日,并将该特定日期替换为平均值。

到目前为止我尝试过的是:

 index <- which(is.na(daily$Precipitation)) # find where the NA's occur
 daily_avg <- daily # copy dataframe
 daily_avg$Date <- strftime(daily_avg$Date, format="2000-%m-%d") # Change the Date format to represent only the day and month and disregard year
 daily_avg <- aggregate(Precipitation~Date, FUN = mean, data = daily_avg, na.rm = TRUE) # find the mean precip per day 
 daily[index,3] <- daily_avg[daily_avg$Date %in% strftime(daily[index,2], format="2000-%m-%d"), 2]

代码中的最后一行无法正常工作,我还不知道为什么。这就是我对这个问题的思考过程。但是,我想知道是否有更好的方法来使用我不知道的内置函数。任何帮助是极大的赞赏。谢谢

【问题讨论】:

    标签: r time-series average replace mean


    【解决方案1】:

    使用data.table

    一些虚拟数据

     set.seed(1)
     library(data.table)
     daily <- seq(as.Date('1948-01-01'),as.Date('1995-12-31')
     dd <- data.table(date = daily, precip = runif(length(daily)))
     # add na values
     nas <- sample(length(daily),300, FALSE)
     dd[, precip := {is.na(precip) <- nas; precip}]
    
    
     ## calculate the daily averages
     # add day and month
     dd[, c('month','day') := list(month(date), mday(date))]
    
     monthdate <- dd[, list(mprecip = mean(precip, na.rm = TRUE)),
                      keyby = list(month, date)]
     # set key for joining
      setkey(dd, month, date)
     # replace NA with day-month averages
     dd[monthdate, precip := ifelse(is.na(precip), mprecip, precip)]
     # set key to reorder to daily
    
     setkey(dd, date)
    

    【讨论】:

      【解决方案2】:

      我认为您示例中的数据没有解释问题。您应该提供多年来某一天的数据,并带有一些 NA 值。例如,这里我在 3 年内更改了 2 天的问题。

      Climate_Division       Date Precipitation
      1                1 1948-07-01     0.2100000
      2                1 1948-07-02            NA
      3                1 1949-07-01     0.1900000
      4                1 1949-07-02     0.1033333
      5                1 1950-07-01            NA
      6                1 1950-07-02     0.1433333
      

      如果我理解的话,这个想法是用所有年份的值的平均值替换 NA 值。您可以使用 avetransform 创建包含均值的新列,然后用它替换 NA 值。

      daily$daymonth <- strftime(daily$Date, format="%m-%d") 
      daily <- transform(daily, mp =ave(Precipitation,daymonth,
                     FUN=function(x) mean(x,na.rm=TRUE) ))
      transform(daily, Precipitation =ifelse(is.na(Precipitation),mp,Precipitation))
      
      
          Climate_Division       Date Precipitation daymonth        mp
      1                1 1948-07-01     0.2100000    07-01 0.2000000
      2                1 1948-07-02     0.1233333    07-02 0.1233333
      3                1 1949-07-01     0.1900000    07-01 0.2000000
      4                1 1949-07-02     0.1033333    07-02 0.1233333
      5                1 1950-07-01     0.2000000    07-01 0.2000000
      6                1 1950-07-02     0.1433333    07-02 0.1233333
      

      【讨论】:

      • @agstudy,我很抱歉没有给出一个很好的例子。你的方法完美!谢谢
      【解决方案3】:

      mnel 答案的一个稍微简洁的版本,我更喜欢接受的版本:

      set.seed(1)
      library(data.table)
      # step 1: form data
      daily <- seq(as.Date('1948-01-01'),as.Date('1995-12-31'),by="day")
      dd <- data.table(date = daily, precip = runif(length(daily)))
      # step 2: add NA values
      nas <- sample(length(daily),300, FALSE)
      dd[, precip := {is.na(precip) <- nas; precip}]
      # step 3: replace NAs with day-of-month across years averages
      dd[, c('month','day') := list(month(date), mday(date))]
      dd[,precip:= ifelse(is.na(precip), mean(precip, na.rm=TRUE), precip), by=list(month,day)]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-01
        • 2020-07-05
        • 2017-06-30
        • 1970-01-01
        • 2019-03-06
        • 2018-06-27
        • 1970-01-01
        • 2021-12-18
        相关资源
        最近更新 更多