Замена строк значениями сразу в нескольких столбцах

#r #string #replace #numbers #recode

#r #строка #заменить #числа #перекодировать

Вопрос:

Мне нужно заменить строки числами в нескольких столбцах. Ниже приведен пример набора данных:

 x <- c("Low Outlier", "High Outlier", "Novice", "Novice", "Emerging", NA, "Proficient", "Approaching")
y <- c("Novice", "Approaching", "Proficient", "Approaching", "High Outlier", "Proficient",NA, "Emerging")
z <- c("High Outlier", "Proficient", "Approaching", "Emerging", "Low Outlier", "Approaching", "Approaching", "Emerging")

sam <- cbind(x,y,z)
  

Мне нужно преобразовать «высокие / низкие выбросы» в 0, NA должны быть оставлены как NA, «Новичок» в 1, «Начинающий» в 2, «Приближающийся к 3» и «Опытный» в 4.

Я попытался преобразовать одну переменную с

 sam$x.r <- recode(sam$x.r,'Low Outlier'=0,'High Outlier'=0,'Novice'=1,'Emerging'=2,'Approaching'=3, 'Proficient'=4)
  

Я получил сообщение об ошибке «Предупреждающее сообщение:
В recode.numeric(Dat17_18.1 $Т.Е.ScoreStat, Low Outlier = 0, High Outlier = 0, :
NAs, введенный принудительно»

Я не уверен, как перекодировать все переменные сразу.

Ответ №1:

Просто сделайте это-

 sam[] <- recode(sam,'Low Outlier'=0,
                    'High Outlier'=0,
                    'Novice'=1,
                    'Emerging'=2,
                    'Approaching'=3, 
                    'Proficient'=4)

> sam
     x   y   z  
[1,] "0" "1" "0"
[2,] "0" "3" "4"
[3,] "1" "4" "3"
[4,] "1" "3" "2"
[5,] "2" "0" "0"
[6,] NA  "4" "3"
[7,] "4" NA  "3"
[8,] "3" "2" "2"
  

Ответ №2:

Очень быстро стало повторяться. Вот простая функция:

 my_replacer<-function(df,y,z){    
df<-as.data.frame(apply(df,2,function(x) gsub(y,z,x)))
    #y is what you want to replace
    #z is the replacement
    #This uses regex
      df
    }
    my_replacer(sam,"Emerging.*","2")
  

Вот как я это использовал:

 library(dplyr)#can use ifelse. Still repetitive

    sam<-as.data.frame(sam)

    sam %>% 
      mutate_if(is.factor,as.character)->sam
    my_replacer(sam,"Emerging.*","2")
  

Результат:

                x            y            z
    1  Low Outlier       Novice High Outlier
    2 High Outlier  Approaching   Proficient
    3       Novice   Proficient  Approaching
    4       Novice  Approaching            2
    5            2 High Outlier  Low Outlier
    6         <NA>   Proficient  Approaching
    7   Proficient         <NA>  Approaching
    8  Approaching            2            2
  

Заменить другие:

 my_replacer(sam,"Novi.*","1")
             x            y            z
1  Low Outlier            1 High Outlier
2 High Outlier  Approaching   Proficient
3            1   Proficient  Approaching
4            1  Approaching     Emerging
5     Emerging High Outlier  Low Outlier
6         <NA>   Proficient  Approaching
7   Proficient         <NA>  Approaching
8  Approaching     Emerging     Emerging
  

Ответ №3:

Мы можем использовать case_when from dplyr для таких случаев

 library(dplyr)

sam %>%
   mutate_all(~case_when(. %in% c("Low Outlier", "High Outlier") ~ '0', 
                   . == "Novice" ~ '1', 
                   . == "Emerging" ~ '2', 
                   . == "Approaching" ~ '3', 
                   . == "Proficient" ~ '4', 
                   TRUE ~ NA_character_))


#     x    y z
#1    0    1 0
#2    0    3 4
#3    1    4 3
#4    1    3 2
#5    2    0 0
#6 <NA>    4 3
#7    4 <NA> 3
#8    3    2 2
  

Однако конечный результат содержит символьные столбцы, поскольку наши исходные столбцы также были символами. Мы можем добавить mutate_all(as.numeric) , чтобы преобразовать их в числовые, если это необходимо.

данные

 x <- c("Low Outlier", "High Outlier", "Novice", "Novice", "Emerging", NA, 
      "Proficient", "Approaching")
y <- c("Novice", "Approaching", "Proficient", "Approaching", "High Outlier", 
      "Proficient",NA, "Emerging")
z <- c("High Outlier", "Proficient", "Approaching", "Emerging", "Low Outlier", 
      "Approaching", "Approaching", "Emerging")
sam <- data.frame(x,y,z, stringsAsFactors = FALSE)
  

Ответ №4:

Я бы использовал именованные векторы в качестве сопоставления

 library(dplyr)
mapping = c("High Outlier" = 0, "Low Outlier" = 0, "Novice" = 1, "Emerging" = 2, "Approaching" = 3, "Proficient" = 4)

sam %>% 
  as.data.frame() %>% 
  mutate_all(function(i) mapping[i])
  

Ответ №5:

Другое решение, использующее factors для перекодирования и approxfun присвоения значений:

 sam[] <- approxfun(1:5, c(0:3, 0))(
      as.numeric(factor(sam, 
                        c("Low Outlier", "Novice",  
                          "Emerging", "Approaching", 
                          "Proficient", "High Outlier"))))

#      x   y   z  
# [1,] "0" "1" NA 
# [2,] NA  "3" "0"
# [3,] "1" "0" "3"
# [4,] "1" "3" "2"
# [5,] "2" NA  "0"
# [6,] NA  "0" "3"
# [7,] "0" NA  "3"
# [8,] "3" "2" "2"