如何用 R 中同一日期不同年份的平均数据替换特定日期的 NA 数据?

How to replace NA data of specific dates with the average data of different years of same dates of a dataframe in R?

如果我有一个数据框A

A = 
year     month     day     hour     minute     rain
                        .
                        .
                        .
2000      01        01      01       00          2
2000      01        01      01       15          2
2000      01        01      01       30          NA
2000      01        01      01       45          3
2000      01        01      02       00          4
2000      01        01      02       15          5
                        .
                        .
                        .

Dataframe A 有 1990 年到 2000 年的数据,频率数据为 15 分钟。

所以 A 具有相同日期和不同年份的特定缺失数据 (NA):

A = 
year     month     day     hour     minute     rain
1990      01        01      01       30          10
                        .
                        .
                        .
1991      01        01      01       30          21
                        .
                        .
                        .
1992      01        01      01       30          4
                        .
                        .
                        .
1993      01        01      01       30          6
                        .
                        .
                        .
1994      01        01      01       30          10
                        .
                        .
                        .
1995      01        01      01       30          23
                        .
                        .
                        .
1996      01        01      01       30          0
                        .
                        .
                        .
1997      01        01      01       30          0
                        .
                        .
                        .
1998      01        01      01       30          0
                        .
                        .
                        .
1999      01        01      01       30          6
                        .
                        .
                        .
2000      01        01      01       30          NA

想法是在 Rain 列中查找每个 NA 数据,并将它们替换为从 1990 年到 2000 年每年同一日期的平均值。

新的 A 将适用于 2000 年:

A = 
year     month     day     hour     minute     rain
                        .
                        .
                        .
2000      01        01      01       00          2
2000      01        01      01       15          2
2000      01        01      01       30          **8**
2000      01        01      01       45          3
2000      01        01      02       00          4
2000      01        01      02       15          5
                        .
                        .
                        .

这可能有用。它将月份和日期对分组,并从平均值中替换 NAs。

library(dplyr)
A <- A %>% 
       group_by(month, day, hour, minute) %>% 
       mutate(rain = ifelse(is.na(rain), 
                              mean(rain, na.rm=TRUE), rain))

使用 的解决方案。思路是将A中的雨按月、日、时、分汇总,按这些列join,然后用平均雨值替换rain中的NA

注意OP更新澄清原问题后,headpoint的回答更加简单明了()。但是,我仍然在这里保留我的答案作为示例,以表明如果替换值来自另一个数据框,则 left_join 方法将很有用。

library(dplyr)

A2 <- A %>%
  left_join(A %>%
              group_by(month, day, hour, minute) %>%
              summarise(mean_rain = mean(rain, na.rm = TRUE)), 
            by = c("month", "day", "hour", "minute")) %>%
  mutate(rain = ifelse(is.na(rain), mean_rain, rain)) %>%
  select(-mean_rain)
A2
#    year month day hour minute rain
# 1  1990     1   1    1     30   10
# 2  1991     1   1    1     30   21
# 3  1992     1   1    1     30    4
# 4  1993     1   1    1     30    6
# 5  1994     1   1    1     30   10
# 6  1995     1   1    1     30   23
# 7  1996     1   1    1     30    0
# 8  1997     1   1    1     30    0
# 9  1998     1   1    1     30    0
# 10 1999     1   1    1     30    6
# 11 2000     1   1    1      0    2
# 12 2000     1   1    1     15    2
# 13 2000     1   1    1     30    8
# 14 2000     1   1    1     45    3
# 15 2000     1   1    2      0    4
# 16 2000     1   1    2     15    5

数据

A <- read.table(text =  "year     month     day     hour     minute     rain
1990      01        01      01       30          10
1991      01        01      01       30          21
1992      01        01      01       30          4
1993      01        01      01       30          6
1994      01        01      01       30          10
1995      01        01      01       30          23
1996      01        01      01       30          0
1997      01        01      01       30          0
1998      01        01      01       30          0
1999      01        01      01       30          6
2000      01        01      01       00          2
2000      01        01      01       15          2
2000      01        01      01       30          NA
2000      01        01      01       45          3
2000      01        01      02       00          4
2000      01        01      02       15          5",
                header = TRUE, stringsAsFactors = FALSE)

这里有一个dplyr方法,它只使用前几年同一时间的平均值。也就是说,与 headpoint 和 www 提供的解决方案相反,这不会使用 01:30、2001 年 1 月 1 日或 2002 年(等)的值来计算用于 01:30、2000 年 1 月 1 日的平均值,但是而是 2000 年 之前 所有年份的 1 月 1 日 01:30 的平均降雨值。

因此,首先,我们只需重新创建要使用的 A 数据框。我只加载 tibble 包以使用 tribble 函数重新创建您的数据框示例。

library(dplyr)
library(tibble)

A <- tribble(
~ year, ~month, ~day, ~hour, ~minute, ~rain,
1990,   01,     01,   01,    30,      10,
1991,   01,     01,   01,    30,      21,
1992,   01,     01,   01,    30,      4,
1993,   01,     01,   01,    30,      6,
1994,   01,     01,   01,    30,      10,
1995,   01,     01,   01,    30,      23,
1996,   01,     01,   01,    30,      0,
1997,   01,     01,   01,    30,      0,
1998,   01,     01,   01,    30,      0,
2000,   01,     01,   01,    00,      2,
2000,   01,     01,   01,    15,      2,
2000,   01,     01,   01,    30,      NA,
2000,   01,     01,   01,    45,      3,
2000,   01,     01,   02,    00,      4,
2000,   01,     01,   02,    15,      5)

然后我们要做的是按月、日、小时和分钟分组,这样我们就可以创建前几年当天那个时间的 运行 平均值。如果下一年有 NA 值,则将使用最近的一个。

A <- A %>% 
  group_by(month, day, hour, minute) %>% 
  mutate(running_mean = round(cummean(rain), 0),
         most_recent_mean = lag(running_mean),
         rain = if_else(is.na(rain), most_recent_mean, rain)) %>%
  select(-running_mean, -most_recent_mean)

这应该可以解决问题。打印结果如下:

# A tibble: 15 x 6
# Groups:   month, day, hour, minute [6]
    year month   day  hour minute  rain
   <dbl> <dbl> <dbl> <dbl>  <dbl> <dbl>
 1  1990     1     1     1     30    10
 2  1991     1     1     1     30    21
 3  1992     1     1     1     30     4
 4  1993     1     1     1     30     6
 5  1994     1     1     1     30    10
 6  1995     1     1     1     30    23
 7  1996     1     1     1     30     0
 8  1997     1     1     1     30     0
 9  1998     1     1     1     30     0
10  2000     1     1     1      0     2
11  2000     1     1     1     15     2
12  2000     1     1     1     30     8
13  2000     1     1     1     45     3
14  2000     1     1     2      0     4
15  2000     1     1     2     15     5 

您可以通过yearmonthday:

将雨柱coalesce平均(没有NA
library(data.table)
library(hutils)

setDT(A)[, 
         rain := coalesce(rain, mean(rain, na.rm = TRUE)),
         keyby = c("year", "month", "day")]

如果您不想安装 hutilsdplyr 的功能几乎相同,但 hutils::coalesce 更快:

 copy(A)[, `:=`(rain2, hutils::coalesce(rain, mean(rain, na.rm = TRUE))),      keyby = c("year", "month", "day")]
  copy(A)[, `:=`(rain2, dplyr::coalesce(rain, mean(rain, na.rm = TRUE))),      keyby = c("year", "month", "day")]
      min       lq     mean   median       uq      max neval cld
 107.1927 118.8372 132.8129 121.4076 128.0383  634.658   100  a 
 887.1115 921.6607 960.4542 943.0711 980.5143 1145.658   100   b

生成示例文件:

A <- 
  CJ(year = 1990:2000,
     month = 1:12,
     day = 1:31,  # yeah I know not all months have 31 days; doesn't matter here
     hour = 0:23,
     minute = 15L * c(0:3))
A[, rain := NA_real_]
A[sample.int(nrow(A), size = 0.8 * nrow(A)), rain := rexp(0.8 * nrow(A), rate = 2)]