用均值和现有值按 id 填充 NA 值

Fill NA values by id with mean and existing values

我有一个数据集,每个 ID 包含三个句点。通过这种方式,如果有 2/3 的值没有 NA(按 id 的现有值的平均值),我将尝试用平均值填充数据集中的 NA 值。另一方面,如果只有 1/3 的值没有 NA,我想用该值填充其余值。我的数据集如下所示:

  ID value period
1203 -0.64 1
1203       2
1203 -0.12 3
1218 0.495 1
1218       2
1218       3

所以,我想用 -0.64-0.12 的平均值填充 ID 1203 中的 NA 值,并且 ID 1218 我想填写 0.495.

这里的好处是,无论有多少个 NA,我们都可以直接输入均值,因为单个数字的均值就是它本身。下面的代码创建了一个类似于你的 table,使用 NA 而不是空格

library(tidyr)

ID=rep(1:10,each=3)
value=runif(30)
value[sample(1:30,10)]=NA
period=rep(1:3,10)


data=data.frame(ID,value,period)

我们需要 tidyr,因为如果我们将您的数据转换为“宽”格式,这会更容易。一旦我们这样做了,我们就可以将平均值应用于新 table 的每一行,对于作为值的列(这就是为什么我们 select 列 2:4,以排除 id 列).

wideData=pivot_wider(data,id_cols=ID,names_from=period,values_from=value)

wideData[,2:4]=apply(wideData[,2:4],1,mean,na.rm=T)

如果您希望数据恢复为原始格式,只需运行以下行将其“加长”即可。

dataLong=pivot_longer(wideData,c(2:4),names_to='period')

如果您对 tidyverse 方法感到满意,则只需使用 mutate() 中的 replace_na() 函数即可。

这会将 value 列中的 NA 替换为 value 的平均值。

library(tidyverse)

df %>% 
  group_by(ID) %>% 
  mutate(value = replace_na(value, mean(value, na.rm = T)))
# A tibble: 6 x 3
# Groups:   ID [2]
  ID     value period
  <chr>  <dbl> <chr> 
1 1203  -0.64  1     
2 1203  -0.38  2     
3 1203  -0.12  3     
4 1218   0.495 1     
5 1218   0.495 2     
6 1218   0.495 3