如何按组均值替换 NA?

How to replace NAs by group mean?

我有两个数据框,一个包含原始数据(和大量 NA),另一个包含不同时间间隔的原始数据的均值。

我想在这些时间间隔内用平均值替换 NA,同时保留非 NA。

我在 "impute missing data r" 或 "replace missing data r" 上搜索了很多,但还没有找到任何似乎合适的解决方案,它们似乎都用 0:s 替换数据,或使用复杂的方法来完成此任务,例如使用 MICE 包。

代码示例: 这是第一个 DF 的头部,带有原始数据。正如你所看到的,第一天他们都是NA。

   steps       date interval
1    NA 2012-10-01        0
2    NA 2012-10-01        5
3    NA 2012-10-01       10
4    NA 2012-10-01       15
5    NA 2012-10-01       20
6    NA 2012-10-01       25
...

第二个数据帧头包含每个间隔的平均步数,如下所示:

  steps interval
1 1.72          0
2 0.340         5
3 0.132        10
4 0.151        15
5 0.0755       20
6 2.09         25
...

现在,我正在寻找的是能够用相关间隔的平均步长填充 NA,所以它看起来像这样:

   steps       date interval
1  1.72  2012-10-01        0
2 0.340  2012-10-01        5
3 0.132  2012-10-01       10
4 0.151  2012-10-01       15
5 0.0755 2012-10-01       20
6 2.09   2012-10-01       25
...

我错过了任何提示或资源链接吗?由于这是一项课程作业,我主要想学习,如果没有为我完成作业而提供任何帮助,将不胜感激! =)

编辑:此外,由于这是我在 Stack Overflow 上提出的第一个问题,任何关于如何改进我的问题制作的评论也非常感谢!

在 R 中有很多方法可以做到这一点。例如

# generate dataframe with some interval vaulues
df1 <- data.frame(interval= rep(seq(0, 25, 5), 5))
# add a steps column
df1$steps <- 1:nrow(df)
# copy the dataframe
df2 <- df1
# replace some steps values with missings in df1
df1$steps[c(1,2,5, 14)] <- NA

# sapply goes thru every unique interval...
sapply(df1$interval, function(interval_i){
  # replace missing steps of interval_i in df1 with the steps mean of interval_i of df2
  df1$steps[is.na(df1$steps) & df1$interval == interval_i] <<- mean(df2$steps[df2$interval == interval_i], na.rm= TRUE)
# you must use <<- not <- to assign it to df outside of sapply
})

我将使用 dplyr 添加解决方案。

最好在问题中提供一些可重现的数据,而不是直接将其放入 R 中,而不仅仅是粘贴到数据的头部。我创建了一些虚拟数据:

# create random sample data
library(dplyr)

set.seed(100)

df1 <- tibble(
  steps = runif(1e3),
  date = lubridate::today() + runif(1e3) * 24,
  interval = as.numeric(sample(seq(0,25, by=5), 1e3, replace = T))
)

# add 100 NAs at random
df1$steps[sample(1:1e3, 100)] <- NA

df1

#      steps  date       interval
#      <dbl>  <date>        <dbl>
# 1   0.308   2019-07-18      15
# 2   NA      2019-07-19      10
# 3   NA      2019-07-31       0
# 4   0.0564  2019-08-02      20
# 5   0.469   2019-07-25       0
# 6   0.484   2019-07-21      25
# 7   NA      2019-07-17       5
# 8   0.370   2019-07-28       0
# 9   0.547   2019-07-31       5
# 10  0.170   2019-08-08      15
# # … with 990 more rows

使用 dplyr 插补任务就非常简单 group_by

df1 %>%
  group_by(interval) %>%
  mutate(steps = if_else(is.na(steps), mean(steps, na.rm = T), steps))

# # A tibble: 1,000 x 3
# # Groups:   interval [6]
#     steps  date       interval
#     <dbl>  <date>        <dbl>
# 1   0.308  2019-07-18       15
# 2   0.573  2019-07-19       10
# 3   0.523  2019-07-31        0
# 4   0.0564 2019-08-02       20
# 5   0.469  2019-07-25        0
# 6   0.484  2019-07-21       25
# 7   0.527  2019-07-17        5
# 8   0.370  2019-07-28        0
# 9   0.547  2019-07-31        5
# 10  0.170  2019-08-08       15
# # … with 990 more rows

我们可以通过计算每组的均值并将其与估算值进行比较来确认每组的估算均值是正确的:

df1 %>%
 group_by(interval) %>% 
 summarise(mean_int = mean(steps, na.rm=T))


# # A tibble: 6 x 2
#     interval mean_int
#     <dbl>    <dbl>
# 1        0    0.523
# 2        5    0.527
# 3       10    0.573
# 4       15    0.511
# 5       20    0.475
# 6       25    0.485