检查每月的日期,修复缺失的值

时间:2015-11-11 19:35:03

标签: r

我需要检查天气数据集中的所有月份,以确保每个站点的每一天都有值。如果缺少天数,或者有-9999那么我想使用均值。在我的原始代码中,我实际上将使用最近的气象站,但出于测试目的,我只使用该月的平均值。

我正在寻找一种更有效的方法来编码这个问题。如何使此代码更有效?这看起来像是一个黑客工作,但我不知道另一种方法。我很感激任何建议。

dput:

    df <- structure(list(id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L), .Label = "USC00036918", class = "factor"), 
    element = structure(c(7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 
    7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 
    7L, 7L, 7L, 7L, 7L), .Label = c("DAPR", "MDPR", "PRCP", "SNOW", 
    "SNWD", "TMAX", "TMIN", "TOBS", "WT01", "WT03", "WT04", "WT05", 
    "WT06", "WT07", "WT08", "WT10", "WT11", "WT14", "WT16", "WT18"
    ), class = "factor"), year = c(1900, 1900, 1900, 1900, 1900, 
    1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 
    1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 
    1900, 1900, 1900, 1900), month = c(1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1), day = c("01", "02", "03", "04", "05", "06", "07", 
    "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", 
    "18", "19", "21", "22", "23", "24", "25", "26", "28", "29", 
    "30", "31"), date = c("19000101", "19000102", "19000103", 
    "19000104", "19000105", "19000106", "19000107", "19000108", 
    "19000109", "19000110", "19000111", "19000112", "19000113", 
    "19000114", "19000115", "19000116", "19000117", "19000118", 
    "19000119", "19000121", "19000122", "19000123", "19000124", 
    "19000125", "19000126", "19000128", "19000129", "19000130", 
    "19000131"), value = c(19.94, 15.08, 12.92, 28.04, 39.92, 
    46.04, 44.96, 37.94, 50, 53.06, 42.98, 28.04, 33.98, 39.92, 
    -9999, 53.96, 53.06, 39.92, 37.94, 33.08, 30.92, 35.06, 42.08, 
    37.04, 23, 26.06, 12.92, 19.94, 21.92)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -29L), .Names = c("id", 
"element", "year", "month", "day", "date", "value"))

代码:

# Get number of days in month
c_month <- paste0(df[1,3], "-", df[1,4], "-01" )
n_month <- paste0(df[1,3], "-", as.numeric(1+df[1,4]), "-01")
days <- as.numeric(difftime( as.Date(n_month), as.Date(c_month) ))
days_count <- as.numeric(1:days)


# Check df for number of days
n_days <- nrow(df)
n_days_count <- as.numeric(df$day)

# Find differences
diff <- setdiff(days_count, n_days_count)
miss <- which(df$value == -9999)

# If -9999 exists, replace with mean
if (length(miss >= 1)) {
  check <- filter(df, value != -9999)
  df[miss,7] = mean(check$value)
}

# If days are missing, insert with mean  
if (n_days < days){
  for (i in 1:length(diff)){
    add_df <- df[1,]
    add_df$day <- diff[i]
    add_df$date <- paste0(add_df$year, add_df$month, diff[i])
    add_df$value <- mean(check$value)
    df <- rbind(df, add_df)
  }
}

1 个答案:

答案 0 :(得分:1)

这是使用一点dplyr的解决方案。

首先,我们将date列放在一起,将您的年,月和日列粘贴在一起。

然后我们创建一个数据框,其中包含从最小日期到最大日期的序列。

然后我们将两者合并以将缺失的天数添加到您的数据中:

df$date <- as.Date(paste0(df$year, "-", df$month, "-", df$day))
tomerge <- data.frame(date = seq(min(df$date), max(df$date), "days"))
newdat <- merge(tomerge, df, by = "date", all.x = TRUE)

接下来,我们按年份和月份进行分组,并使用该月的平均值填写所有NAs:

library(dplyr)
library(lubridate)

newdat %>% mutate(value = ifelse(value == -9999, NA, value)) %>%
           group_by(year = year(date), month = month(date)) %>%
           mutate(value = ifelse(is.na(value), mean(value, na.rm=TRUE), value))