我需要检查天气数据集中的所有月份,以确保每个站点的每一天都有值。如果缺少天数,或者有-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)
}
}
答案 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))