【问题标题】:How to replace NA's in numerical columns with the median of those columns? [duplicate]如何用这些列的中位数替换数值列中的 NA? [复制]
【发布时间】:2021-11-19 00:03:00
【问题描述】:

我正在处理具有多种数据类型的数据框。我想仅将 数字列上的 NA 值替换为 该特定列的中位数。我有看到关于用平均值替换的问题,但不是中位数。我的df类似于下面的代码:

my_groups <- c(rep("A", 5), rep("B",5))
my_values_1 <- c(4, 9, 10, NA, 5, 12, NA, 7, 11, 8)
my_values_2 <- c(3, NA, 4, 8, 2, 11, 15, NA, 9, 10)
my_df <- data.frame(my_groups, my_values_1, my_values_2)
my_df %>% select_if(is.numeric)

这给了我数字列,但我不知道下一步。

【问题讨论】:

标签: r dataframe tidyverse


【解决方案1】:

这里有几种方法。测试数据框DF 在(1)中定义,也用于其他方法。

1) dplyr - 交叉/合并

library(dplyr)

# test data
DF <- data.frame(a = c(NA, NA, 1, 2), b = 1:4, c = letters[1:4])

DF %>% 
  mutate(across(where(is.numeric), ~ coalesce(., median(., na.rm = TRUE))))

给予:

    a b c
1 1.5 1 a
2 1.5 2 b
3 1.0 3 c
4 2.0 4 d

2) dplyr/tidyr - cross/replace_na

library(dplyr)
library(tidyr)

DF %>% 
  mutate(across(where(is.numeric), ~ replace_na(., median(., na.rm = TRUE))))

3) 动物园 - na.aggregate

library(zoo)

ok <- sapply(DF, is.numeric)
replace(DF, ok, na.aggregate(DF[ok], FUN = median))

4) 基础R

na.median <- function(x) replace(x, is.na(x), median(x, na.rm = TRUE))   
ok <- sapply(DF, is.numeric)
replace(DF, ok, lapply(DF[ok], na.median))

5) 基础 R - S3

na.median <- function(x, ...) UseMethod("na.median")
na.median.default <- identity
na.median.numeric <- function(x, ...) {
  replace(x, is.na(x), median(x, na.rm = TRUE))   
}

replace(DF, TRUE, lapply(DF, na.median))

6) magrittr 我们首先复制DF 以避免破坏它——虽然不建议你可以在最后一行使用DF,如果你可以覆盖它——并使用 magrittr %&lt;&gt;%na.median 来自 (4)。

library(magrittr)

DF2 <- DF
DF2[sapply(DF2, is.numeric)] %<>% lapply(na.median)

7) collapse - ftmv ftmv 或其同义词 ftransformv 提供了一个紧凑的表达式。这使用na.median 来自(4)。

library(collapse)

tfmv(DF, is.numeric, na.median)

【讨论】:

    【解决方案2】:

    我们可以将mutateacrossifelse 语句一起使用: 注意:D. Grothendieck 的答案也很完美!

    library(dplyr)
    my_df %>% 
      mutate(across(where(is.numeric), ~ifelse(is.na(.), median(.,na.rm=TRUE), .)))
    

    输出:

       my_groups my_values_1 my_values_2
    1          A         4.0         3.0
    2          A         9.0         8.5
    3          A        10.0         4.0
    4          A         8.5         8.0
    5          A         5.0         2.0
    6          B        12.0        11.0
    7          B         8.5        15.0
    8          B         7.0         8.5
    9          B        11.0         9.0
    10         B         8.0        10.0
    

    【讨论】:

      【解决方案3】:

      case_when 的选项

      library(dplyr)
       my_df %>% 
         mutate(across(where(is.numeric), 
           ~ case_when(is.na(.) ~ median(., na.rm = TRUE), TRUE ~ .)))
      

      -输出

       my_groups my_values_1 my_values_2
      1          A         4.0         3.0
      2          A         9.0         8.5
      3          A        10.0         4.0
      4          A         8.5         8.0
      5          A         5.0         2.0
      6          B        12.0        11.0
      7          B         8.5        15.0
      8          B         7.0         8.5
      9          B        11.0         9.0
      10         B         8.0        10.0
      

      【讨论】:

        猜你喜欢
        • 2016-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-07
        • 1970-01-01
        • 2016-04-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多