如何根据最大值重新编码数据框列?

How to recode data frame columns depending on maximum values?

我有一个包含几十列和几千行的数据框。我想重新编码最大值为 8 的数字列,使 8 变为 NA,并重新编码最大值为 9 的数字列,使 8 变为 NA,9 变为 9999。对于例如,

mydf <- data.frame(a = c(1, 2, 8, 9), b = c(7, 8, 9, 10), c = c(4, 5, 6, 9), d = c(5, 6, 7, 8), e = c("a", "b", "c", "d"))

> mydf
  a  b c d e
1 1  7 4 5 a
2 2  8 5 6 b
3 8  9 6 7 c
4 9 10 9 8 d

会变成:

> mydf
     a  b    c  d e
1    1  7    4  5 a
2    2  8    5  6 b
3   NA  9    6  7 c
4 9999 10 9999 NA d

我想到了这样做:

mydf1 <- mydf[,sapply(mydf, max) == 8]
mydf2 <- mydf[,sapply(mydf, max) == 9]
mydf1[mydf1 == 8] <- NA
mydf2[mydf2 == 8] <- NA
mydf2[mydf2 == 9] <- 9999

但我不知道如何将重新编码的变量从新数据帧带回原始数据帧——而且我确信无论如何还有更有效的解决方案。

您可以使用 lapply 检查每列的 max 值,如果它是 8 或 9 则重新编码。

mydf[] <- lapply(mydf, function(x) {
  if(max(x) %in%  c(8, 9)) {
    x[x == 8] <- NA
    x[x == 9] <- 9999
  }
  x
})
mydf

#     a  b    c  d e
#1    1  7    4  5 a
#2    2  8    5  6 b
#3   NA  9    6  7 c
#4 9999 10 9999 NA d

我们可以使用 tidyverse 方法动态检查列是否为数字,然后循环 across 这些列,检查 8 或 9 是否 %in% max值,然后使用 na_if 将 8 替换为 NA 并使用 replace 将 9 更改为 9999

library(dplyr)
mydf %>%
    mutate(across(where(is.numeric), ~
   if(any(c(8, 9) %in% max(., na.rm = TRUE))) replace(na_if(., 8), .==9, 9999)))
#     a    c  d e
#1    1    4  5 a
#2    2    5  6 b
#3   NA    6  7 c
#4 9999 9999 NA d