使用 for 循环用中位数替换数据框中的 NA 值

时间:2021-04-13 13:04:33

标签: r

我一直在努力研究如何使用 for 循环将某些列中的 NA 值替换为列的中位数。 到目前为止,我有这个:

for (i in 1:ncol(merged_df_edit3)){
  if(is.na(merged_df_edit3[,i]) == TRUE){
    assign(merged_df_edit3[,i],replace_na(median(merged_df_edit3[,i])))
  }

}

这有效并运行,但给出警告:

<块引用>

"在 if (is.na(merged_df_edit3[, i]) == TRUE) { ... : 条件 长度 > 1 并且只使用第一个元素"

但是,当我检查数据框时,它根本没有替换任何值。

我使用的数据在数字、日期和字符之间混合,就像这样。 字符列中有一些空白,但我不需要填充它们。

df <- tribble(
  ~`date Column`,   ~`Numeric Column`,  ~`Character Column`,
  "1/1/2011",   123,    "Left",
  "1/2/2011",   124,    "Right",
  "1/3/2011",   125,    "Left",
  "1/4/2011",   NA,   "NA",
  "1/5/2011",   132,    "Right"
)

谢谢!

3 个答案:

答案 0 :(得分:3)

只需要一个 for 循环和一个 if 条件。

for(i in 1:ncol(df)){
  if(is.numeric(df[[i]])){
    na <- is.na(df[[i]])
    df[na, i] <- median(df[[i]], na.rm = TRUE)
  }
}

答案 1 :(得分:1)

您可以使用 dplyr 代替循环,这可能会更有效:

library(dplyr)

df <- df %>%
      mutate(across(where(is.numeric),function(x) {if_else(is.na(x),median(x,na.rm=T),x)}))

答案 2 :(得分:1)

如果您坚持使用 for 循环,这里有一个可能对您有所帮助的解决方案。应该注意的是,我首先检查列是否为数字,然后遍历其行以找到 NA 值。

df <- tribble(
  ~`date Column`,   ~`Numeric Column`,  ~`Character Column`,
  "1/1/2011",   123,    "Left",
  "1/2/2011",   124,    "Right",
  "1/3/2011",   125,    "Left",
  "1/4/2011",   NA,   "NA",
  "1/5/2011",   132,    "Right"
)

for(j in 1:ncol(df)) {
  if(is.numeric(df[[j]])) {
    for(i in 1:nrow(df)) {
      if(is.na(df[i, j])) {
        df[i, j] <- median(df[[j]], na.rm = TRUE)
      }
    }
  }
}
df

# A tibble: 5 x 3
  `date Column` `Numeric Column` `Character Column`
  <chr>                    <dbl> <chr>             
1 1/1/2011                  123  Left              
2 1/2/2011                  124  Right             
3 1/3/2011                  125  Left              
4 1/4/2011                  124. NA                
5 1/5/2011                  132  Right 

Numeric Column 的第 4 个元素已被该列的中位数替换。