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

问题描述

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

mydf <- data.frame(a = c(1,2,8,9),b = c(7,9,10),c = c(4,5,6,d = c(5,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[,max) == 9]
mydf1[mydf1 == 8] <- NA
mydf2[mydf2 == 8] <- NA
mydf2[mydf2 == 9] <- 9999

但是我不知道如何将新数据帧中的重新编码的变量带回到原始数据帧中,而且我敢肯定还有更有效的解决方案。

解决方法

您可以使用max检查每一列的lapply值,并重新编码是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