2013-03-20 100 views
0

我有一个名为日常数据框,看起来像这样:平均多年来每日数据中的R替换NA值

 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

我想在您的示例中的数据,也不能说明问题。您应该在多年的某个特定日期提供一些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值。 MNEL的答案,我宁愿接受一个

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 
+0

+ 1(...,格式= '%间%d') ' – mnel 2013-03-20 05:15:09

+1

@agstudy,我对没有给出一个好例子表示歉意。你的方法完美无缺!谢谢 – 2013-03-20 06:05:07

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) 
1

稍微整洁版本:`strftime的

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)]