简体   繁体   中英

How to recode only selected columns in R

I have a data frame with the following column names and values:

|     ss1         |     ss2      |      ss3        |          
|Strongly Agree   |Disagree      |Agree            |
|Agree            |Agree         |Disagree         |
|Strongly Disagree|Agree         |Disagree         |
|Disagree         |Strongly Agree|Strongly Disagree|

I am looking for a way to only recode the columns ss1 and ss3 in way that

Strongly Agree - 1
Agree - 2
Disagree - 3
Strongly Disagree - 4

But the ss2 column should be recoded in reverse meaning Strongly Disagree - 1, Disagree - 2, Agree - 3 and Strongly Agree - 4 so far I have tried the following code:

If((names(df=="ss1")) |(names(df=="ss3"))) {
   lapply(df, 
     FUN = function(x) recode(x, 
        "'Strongly Disagree'=4; 
         'Disagree'=3; 
         'Agree'=2; 
         'Strongly Agree'=1; 
         'No Opinion'=''"))}

I know that my execution statement can only be used to recode all columns. Is there any way to limit the recoding only to column names that match the IF expression?

Also is there a way to use a logical 'OR' in my IF condition?

The reason why I want to keep the IF condition is because I want to match the column name and then give the recode condition.

The output will look like:

|     ss1         |     ss2      |      ss3        |          
|1                |2             |2                |
|2                |3             |3                |
|4                |3             |3                |
|3                |4             |4                |

I am sorry if the question is a bit unclear.

Here's how to do it with dplyr . If you want to recode columns, use mutate_at with recode (as suggested by apom). You need 2 different mutate_at because the order is different for ss1,ss3 and ss2.

library(dplyr)
df1  <- read.table(text="ss1              ss2            ss3
'Strongly Agree'   Disagree      Agree
Agree            Agree         Disagree
'Strongly Disagree' Agree         Disagree
Disagree         'Strongly Agree' 'Strongly Disagree'", header=TRUE, stringsAsFactors=FALSE)

df1 %>%
mutate_at(.cols= vars(ss1,ss3),
 .funs = funs(recode(., 'Strongly Disagree' = 4, 'Disagree' = 3, 'Agree' = 2,
 'Strongly Agree' = 1, .default = NA_real_)) ) %>%
mutate_at(.cols= vars(ss2),
 .funs = funs(recode(., 'Strongly Disagree' = 1, 'Disagree' = 2, 'Agree' = 3,
 'Strongly Agree' = 4, .default = NA_real_)) )
  ss1 ss2 ss3
1   1   2   2
2   2   3   3
3   4   3   3
4   3   4   4

a fast solution using data.table

library(data.table)

# function to reclassify columns
  myfun = function(x)  { ifelse(x=='Strongly Disagree', 4,
                       ifelse(x=='Disagree', 3,
                       ifelse(x=='Agree', 2,
                       ifelse(x=='Strongly Agree', 1,"")))) }

# indicate which columns should be transformed
  cols <- c('ss1', 'ss3')

# Reclassify columns
  setDT(df1)[, (cols) := lapply (.SD, myfun), .SDcols=cols]

Or use joins, as suggested by @Frank:

library(data.table)
setDT(df1)

cols <- c('ss1', 'ss3')
recDT = data.table(
  old = c('Strongly Disagree', 'Disagree', 'Agree', 'Strongly Agree'), 
  new = 4:1)

for (col in cols) df1[recDT, on=setNames("old", col), paste0(col, "_new") := i.new]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM