【问题标题】:Replacing NA Values in a data frame with the median using a for loop使用 for 循环将数据框中的 NA 值替换为中值
【发布时间】:2021-07-08 13:02:21
【问题描述】:

我一直在尝试研究如何使用 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"
)

谢谢!

【问题讨论】:

  • 能否请您包含一些代码来生成示例数据集,以及加载您使用的包的代码? replace_na() 不是基本函数。
  • 需要注意的是is.na对其输入进行矢量化操作。所以它返回一个与输入长度相同的逻辑向量。当您将其放入 if 语句时,只会检查第一个元素,因为 if 不会遍历向量,为此我们需要一个 for 循环。

标签: r


【解决方案1】:

只需要一个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)
  }
}

【讨论】:

  • 谢谢你亲爱的瑞,我还没有这么想过。我觉得这也比我的快一点。
【解决方案2】:

如果您坚持使用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 个元素已被该列的中位数替换。

【讨论】:

    【解决方案3】:

    您可以使用dplyr 而不是循环,这可能会更有效:

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

    【讨论】:

    • 由于注意到只有数字列中的NA 值被该列的中值替换,对于这个问题,使用where(is.numeric) 可能比everything() 更合适。
    • 我很高兴亲爱的瓦尔迪。
    • 感谢 Waldi,我以前从未使用过 cross 函数!
    猜你喜欢
    • 2023-02-24
    • 2021-08-10
    • 2020-07-04
    • 2021-08-30
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 2018-09-11
    • 1970-01-01
    相关资源
    最近更新 更多