首页 > 解决方案 > 如何根据另一个数据帧的值填写数据帧中的 NA(平均值/中位数)?

问题描述

我有一个 df,我想为每个唯一 ID 运行关于它们在 Value 列中的值的 Shapiro 测试,并将结果放入数据表 (dt_table) 中。我还编写了几行代码,以便再次用每个唯一 ID 的平均值替换 NA。但是我真正想要检查 dt_table 并且如果列“accept_H1”为 TRUE,则将 NA 替换为中位数,但如果为 FALSE,则将 NA 替换为平均值

dput(df)
structure(list(ID = c("F1", "F1", "F1", "F1", "F1", "F1", "F1", 
"F2", "F2", "F2", "F2", "F2", "F2", "F2", "F2", "F3", "F3", "F3", 
"F3", "F3", "F3", "F3", "F3", "F3", "F4", "F4", "F4", "F4", "F4", 
"F4", "F4", "F4"), Values = c(9.6, NA, 10.2, 9.8, 9.9, 9.9, 9.9, 
1.2, 1.2, 1.8, 1.5, 1.5, 1.6, 1.4, NA, 3266, 3256, 7044, 6868, 
NA, 3405, 3410, NA, 5567, 59.4, 56, 52.8, 52.4, 55.5, NA, NA, 
53.6)), class = "data.frame", row.names = c(NA, -32L))

这是夏皮罗测试和我放置结果的数据表。

dt_list <- by(df, df$ID, function(sub) {
  results <- shapiro.test(sub$Values)
  
  data.table(
    ID = sub$ID[1],
    Wilk = results$statistic,
    p_value = results$p.value,
    accept_H1 = results$p.value <= 0.05
  )
})

dt_table <- data.table::rbindlist(dt_list)

这些是用每个 ID 的平均值替换所有 NA 的几行代码。我想检查 data_table,例如,如果对于 F1,“accept_H1”列是 TRUE,那么我想用中位数替换 F1 的 NA,但它是 FALSE,然后我想用平均值替换它们。有人可以帮忙吗?

df %>% 
  group_by(ID) %>% 
  mutate(Values = ifelse(is.na(Values), mean(Values,na.rm=TRUE), Values))

标签: rdataframereplace

解决方案


我们可能需要与“dt_table”进行连接或合并,然后使用if/else条件。使用na.aggregatefrom可能会更好,zoo因为这更容易

library(data.table)
library(zoo)
setDT(df)[dt_table[, .(ID, accept_H1)], accept_H1 := accept_H1, on = .(ID)]
df[,Values := if(first(accept_H1)) na.aggregate(Values, FUN = median) else 
           na.aggregate(Values), ID][, accept_H1 := NULL][]

-输出

> df
    ID      Values
 1: F1    9.600000
 2: F1    9.883333
 3: F1   10.200000
 4: F1    9.800000
 5: F1    9.900000
 6: F1    9.900000
 7: F1    9.900000
 8: F2    1.200000
 9: F2    1.200000
10: F2    1.800000
11: F2    1.500000
12: F2    1.500000
13: F2    1.600000
14: F2    1.400000
15: F2    1.457143
16: F3 3266.000000
17: F3 3256.000000
18: F3 7044.000000
19: F3 6868.000000
20: F3 3410.000000
21: F3 3405.000000
22: F3 3410.000000
23: F3 3410.000000
24: F3 5567.000000
25: F4   59.400000
26: F4   56.000000
27: F4   52.800000
28: F4   52.400000
29: F4   55.500000
30: F4   54.950000
31: F4   54.950000
32: F4   53.600000
    ID      Values

或者这也可以在不合并的情况下完成。即我们可以match从'dt_table'中使用对应的'ID'分组值,使用索引提取'accept_H1'以用于if/else条件

library(dplyr)
df %>% 
    group_by(ID) %>%
    mutate(Values = if(dt_table$accept_H1[match(cur_group()$ID, 
         dt_table$ID)]) na.aggregate(Values, FUN = median) else
           na.aggregate(Values)) %>% 
    ungroup
# A tibble: 32 x 2
   ID    Values
   <chr>  <dbl>
 1 F1      9.6 
 2 F1      9.88
 3 F1     10.2 
 4 F1      9.8 
 5 F1      9.9 
 6 F1      9.9 
 7 F1      9.9 
 8 F2      1.2 
 9 F2      1.2 
10 F2      1.8 
# … with 22 more rows

推荐阅读