Reputation: 113
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.
Upvotes: 3
Views: 2220
Reputation: 13807
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]
Upvotes: 2
Reputation: 16277
Here's how to do it with dplyr
. If you want to recode columns, use mutate_at
with recode
(as suggested by a p o m). 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
Upvotes: 2