R语言 在不同类别的多个列中替换NA

pkbketx9  于 2023-06-27  发布在  其他
关注(0)|答案(4)|浏览(152)

我有多个列的数据,它们的名称相似,但属于不同的类。我需要用0替换所有的NA,但保留columns类,因为不同的字符串将在以后被赋予其他数值。
这是示例数据:

qdf = data.frame(bicep_wt = c("black band", "5", NA),
                 tricep_wt = c(2,NA,3))

这是我尝试将NA改为0的结果:

mutate(qdf, across(contains("wt"), ~case_when(is.numeric(.x) ~ tidyr::replace_na(., 0),
                                              is.character(.x) ~ tidyr::replace_na(., "0"))))

我收到错误:

Error in `mutate()`:
i In argument: `across(...)`.
Caused by error in `across()`:
! Can't compute column `bicep_wt`.
Caused by error in `case_when()`:
! Failed to evaluate the right-hand side of formula 1.
Caused by error in `vec_assign()`:
! Can't convert `replace` <double> to match type of `data` <character>.

相同错误:

mutate(qdf, across(contains("wt"), ~case_when(is.numeric(.x) ~ tidyr::replace_na(.x, 0),
                                              is.character(.x) ~ tidyr::replace_na(.x, "0"))))
z18hc3ub

z18hc3ub1#

虽然“类安全”通常是一件好事,但可以有利地使用非类安全的函数。

mutate(qdf, across(contains("wt"), ~ replace(.x, is.na(.x), 0)))
#     bicep_wt tricep_wt
# 1 black band         2
# 2          5         0
# 3          0         3

所谓“类安全”,我的意思是保证类从表达式返回。比如说

ifelse(c(T, T), 1, "1")
# [1] 1 1
ifelse(c(T, F), 1, "1")
# [1] "1" "1"

第一个调用是不明确的,因为yes=是类数字,而no=是类字符。一个类安全的函数应该抱怨这一点,如

dplyr::if_else(c(T, T), 1, "1")
# Error in dplyr::if_else(c(T, T), 1, "1") : 
#   Can't combine `true` <double> and `false` <character>.
data.table::fifelse(c(T, T), 1, "1")
# Error in data.table::fifelse(c(T, T), 1, "1") : 
#   'yes' is of type double but 'no' is of type character. Please make sure that both arguments have the same type.

请注意,ifelsereplace是 * 非 * 类安全的,但在这种情况下,根据您的需求,它是可以接受的。

5tmbdcev

5tmbdcev2#

您可以将条件传递到replace_na内部:

mutate(qdf, across(contains("wt"), ~ replace_na(.x, `if`(is.numeric(.x), 0, "0"))))

结果:

bicep_wt tricep_wt
1 black band         2
2          5         0
3          0         3

Obs:它可以与ifelse()或``if()一起工作。

slmsl1lt

slmsl1lt3#

mutate(
  qdf, 
  across(
    contains("wt"), 
    \(.x) { # could use ~ instead
      if      (is.numeric(.x)  ) tidyr::replace_na(.x, 0)
      else if (is.character(.x)) tidyr::replace_na(.x, "0")
    }
  )
)

#     bicep_wt tricep_wt
# 1 black band         2
# 2          5         0
# 3          0         3
t9aqgxwy

t9aqgxwy4#

如果您不知道您的列将仅为数字或字符,您可以做一个版本,无论如何都将替换正确的NA类型。

1)带循环

for (col in colnames(qdf)) {
  qdf[is.na(qdf[, col]), col] <- 0
}

2)带函数和lapply()

naToZero <- function(v) {
  v[is.na(v)] <- 0
  return(v)
}
qdf <- data.frame(lapply(X=qdf, FUN=function(u) naToZero(u)))
qdf
    bicep_wt tricep_wt
1 black band         2
2          5         0
3          0         3

相关问题