I am trying to recode a variable which contains the labels of the answers as a character into numeric values. I am using recode()
from dplyr for this.
To automate this I wanted to use paste()
to generate the variable names but apparently recode()
can't take the output from paste
.
I already tried noquote()
and as.name()
but for both R tells me that recode can't use objects of the class "noquote"/"name".
Example:
item1 <- c("Don't agree at all", "Totally agree")
item2 <- c("Indifferent", "Totally agree")
for (i in 1:2) {
recode(paste("item", i, sep=""), "Totally agree"=1, "Indifferent"=2, "Don't agree at all"=3)
}
I would then expect
> item1
[1] 3 1
How can I solve this?
UPDATE
I found a work around by first extracting the relevant columns into another dataframe and then applying the recode()
function with sapply()
. Now I can remerge the dataframes.
Regarding "but apparently recode() can't take the output from paste.": This has nothing to do with recode
but (almost) any R function works this way. paste
returns a string, and recode
expects a vector as its first argument... (notable exception, amongst others: library
where we can pass a string or the library name as an object).
What you could do, if you insist on the "for loop" approach is to use a combination of assign
and something like eval(sym("a string"))
:
item1 <- c("Don't agree at all", "Totally agree")
item2 <- c("Indifferent", "Totally agree")
library(dplyr)
for (i in 1:2) {
assign(paste("item", i, sep="") , recode(eval(sym(paste("item", i, sep=""))), "Totally agree"=1, "Indifferent"=2, "Don't agree at all"=3))
}
That results in:
item1
[1] 3 1
item2
[1] 2 1
A probably more straightforward and a bit more "dplyr"-y approach would be something along the lines of:
tdd <- data.frame(item1, item2) %>%
mutate_at(vars(starts_with("item")), ~recode(., "Totally agree"=1, "Indifferent"=2, "Don't agree at all"=3))
And tdd
is now:
tdd
item1 item2 1 3 2 2 1 1
You simply could put a named vector v
together with a list of your variables from mget
into Map
and subset it.
v <- c("Totally agree"=1, "Indifferent"=2, "Don't agree at all"=3)
Map(function(x, y) unname(y[x]), mget(ls(pattern="^item")), list(v))
# $item1
# [1] 3 1
#
# $item2
# [1] 2 1
Or, suppose you have a data frame like this one,
head(dat1)
# id item1 item2 x
# 1 1 Totally agree Totally agree 0.0356312
# 2 2 Totally agree Totally agree 1.3149588
# 3 3 Totally agree Indifferent 0.9781675
# 4 4 Totally agree Indifferent 0.8817912
# 5 5 Indifferent Indifferent 0.4822047
# 6 6 Indifferent Don't agree at all 0.9657529
then you may do this in a similar way. We may even simplify the code because we don't need the Map
to return unname
d objects anymore.
v1 <- c("Totally agree"=1, "Indifferent"=2, "Don't agree at all"=3)
item_nm <- c("item1", "item2")
dat1[item_nm] <- Map(`[`, list(v1), dat2[item_nm])
dat1
# id item1 item2 x
# 1 1 1 1 0.0356312
# 2 2 1 1 1.3149588
# 3 3 1 2 0.9781675
# 4 4 1 2 0.8817912
# 5 5 2 2 0.4822047
# 6 6 2 3 0.9657529
# 7 7 2 3 -0.8145709
# 8 8 1 1 0.2839578
# 9 9 3 1 -0.1616986
# 10 10 3 3 1.9355718
The second argument gets recycled for each Map
iteration (ie list(v1, v1)
would also work).
And more generally, for each column you want to recode numerically, list
one vector more in the second argument of Map
.
head(dat2)
# id item1 item2 x
# 1 1 Totally agree Always 0.0356312
# 2 2 Totally agree Always 1.3149588
# 3 3 Totally agree Both 0.9781675
# 4 4 Totally agree Both 0.8817912
# 5 5 Indifferent Both 0.4822047
# 6 6 Indifferent Never 0.9657529
v2 <- c("Always"=1, "Both"=2, "Never"=3)
dat2[item_nm] <- Map(`[`, list(v1, v2), dat2[item_nm])
dat2
# id item1 item2 x
# 1 1 1 1 0.0356312
# 2 2 1 1 1.3149588
# 3 3 1 2 0.9781675
# 4 4 1 2 0.8817912
# 5 5 2 2 0.4822047
# 6 6 2 3 0.9657529
# 7 7 2 3 -0.8145709
# 8 8 1 1 0.2839578
# 9 9 3 1 -0.1616986
# 10 10 3 3 1.9355718
Data:
dat1 <- structure(list(id = 1:10, item1 = c("Totally agree", "Totally agree",
"Totally agree", "Totally agree", "Indifferent", "Indifferent",
"Indifferent", "Totally agree", "Don't agree at all", "Don't agree at all"
), item2 = c("Totally agree", "Totally agree", "Indifferent",
"Indifferent", "Indifferent", "Don't agree at all", "Don't agree at all",
"Totally agree", "Totally agree", "Don't agree at all"), x = c(0.0356311982051355,
1.31495884897891, 0.978167526364279, 0.881791226863203, 0.482204688262918,
0.965752878105794, -0.814570938270238, 0.283957806364306, -0.161698647607024,
1.93557176599585)), class = "data.frame", row.names = c(NA, -10L
))
dat2 <- structure(list(id = 1:10, item1 = c("Totally agree", "Totally agree",
"Totally agree", "Totally agree", "Indifferent", "Indifferent",
"Indifferent", "Totally agree", "Don't agree at all", "Don't agree at all"
), item2 = c("Always", "Always", "Both", "Both", "Both", "Never",
"Never", "Always", "Always", "Never"), x = c(0.0356311982051355,
1.31495884897891, 0.978167526364279, 0.881791226863203, 0.482204688262918,
0.965752878105794, -0.814570938270238, 0.283957806364306, -0.161698647607024,
1.93557176599585)), class = "data.frame", row.names = c(NA, -10L
))
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.