【问题标题】:how fill in NAs (mean/median) in a dataframe depending on the values of another dataframe?如何根据另一个数据帧的值填写数据帧中的 NA(平均值/中位数)?
【发布时间】:2021-08-06 07:58:08
【问题描述】:

我有一个 df,我想针对每个唯一 ID 运行 Shapiro 测试,了解它们在 Value 列中的值,并将结果放入数据表 (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))

【问题讨论】:

    标签: r dataframe replace


    【解决方案1】:

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

    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
    

    【讨论】:

    • 它似乎工作但我们可以分配``` df[,Values := if(first(accept_H1)) na.aggregate(Values, FUN = median) else na.aggregate(Values), ID][, accept_H1 := NULL][]``` 在同一个数据帧 df?目前它在 Rstudio @akrun 的控制台中生成整个数据集
    • @pipts 它正在更新与我们在 data.table 中 := 所做的相同的数据集
    • aww 抱歉,我不得不关闭数据框并重新打开它。它奏效了,谢谢。您认为这种方法正确吗?我的意思是运行 Shapiro 测试并根据 shapiro @akrun 的结果用平均值或中位数替换 NAs
    • @pipts 抱歉,您指的是来自“威尔克”的专栏。我使用的方法是从'dt_table'中获取accept_H1 f,如果它是TRUE,则用'Values'列中的中位数替换NA,否则mean
    • 这正是我想要做的。我在统计方面询问这种方法(根据 shapiro 输出将 NA 替换为均值/中值)对您是否正确,或者您会做其他事情吗? @akrun
    猜你喜欢
    • 2021-01-26
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多