平均多年的每日数据以替换R中的NA值

时间:2013-03-20 04:25:47

标签: r time-series average replace mean

我有一个名为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行具有1948年7月7日的NA,我将从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]

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

3 个答案:

答案 0 :(得分:3)

我认为你的例子中的数据,不解释问题。您应该使用一些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

答案 1 :(得分:2)

使用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 :(得分:1)

一个稍微整洁的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)]