Reputation: 101
I would like to recode multiple variables at once in R. The variables are within a larger dataframe. Here is some example data:
z <- data.frame (A = c(1,2,300,444,555),
B = c(555,444,300,2,1),
C = c(1,2,300,444,555),
D = c(1,2,300,444,555))
What I would like to do is recode all values that equal 300 as 3, 444 as 4, and 555 as 5.
I thought I could possibly do this in a list. Here is what I tried:
example_list = list(c("A", "B", "C", "D"))
example_list <- apply(z[,example_list], 1, function(x) ifelse(any(x==555, na.rm=F), 0.5,
ifelse(any(x==444), 0.25),
ifelse(any(x==300), 3, example_list)))
I get this error:
Error during wrapup: invalid subscript type 'list'
Then tried using "lapply" and I got this error:
Error during wrapup: '1' is not a function, character or symbol
Even then I'm not sure this is the best way to go about doing this... I would just like to avoid doing this line by line for multiple variables. Any suggestions would be amazing, as I'm new to R and don't entirely understand what I'm doing wrong.
I did find a similar questions on SO: Question, but I'm not sure how to apply that to my specific problem.
Upvotes: 4
Views: 2658
Reputation: 43
If you alredy have factor variables and also want factor variables as result you can use the following code:
library(tidyverse)
z <- data.frame (A = factor(c(1,2,300,444,555)),
B = factor(c(555,444,300,2,1)),
C = factor(c(1,2,300,444,555)),
D = factor(c(1,2,300,444,555)))
new.z <- z %>%
mutate_all(function(x) recode_factor(x, "300" = "3", "444" = "4", "555" = "5"))
Upvotes: 0
Reputation: 93938
Here's a base R attempt which should be neatly extendable and pretty fast:
# set find and replace vectors
f <- c(300,444,555)
r <- c(3, 4, 5)
# replace!
m <- lapply(z, function(x) r[match(x,f)] )
z[] <- Map(function(z,m) replace(m,is.na(m),z[is.na(m)]), z, m)
# A B C D
#1 1 5 1 1
#2 2 4 2 2
#3 3 3 3 3
#4 4 2 4 4
#5 5 1 5 5
Upvotes: 2
Reputation: 4846
z = data.frame (A = c(1,2,300,444,555),
B = c(555,444,300,2,1),
C = c(1,2,300,444,555),
D = c(1,2,300,444,555))
library(expss)
to_recode = c("A", "B", "C", "D")
recode(z[, to_recode]) = c(300 ~ 3, 444 ~ 4, 555 ~ 5)
Upvotes: 0
Reputation: 1668
Using case_when
:
library(dplyr)
z %>% mutate_all(
function(x) case_when(
x == 300 ~ 3,
x == 444 ~ 4,
x == 555 ~ 5,
TRUE ~ x
)
)
A B C D
1 1 5 1 1
2 2 4 2 2
3 3 3 3 3
4 4 2 4 4
5 5 1 5 5
Upvotes: 2
Reputation: 1709
This should work.
library(plyr)
new.z<- apply(z, 1, function(x) mapvalues(x, from = c(300, 444, 555), to = c(3, 4, 5)))
Upvotes: 1
Reputation: 10203
This seems a bit clunky but it works:
mutate_cols <- c('A', 'B')
z[, mutate_cols] <- as.data.frame(lapply(z[, mutate_cols], function(x) ifelse(x == 300, 3,
ifelse(x == 444, 4,
ifelse(x== 555, 5, x)))))
Upvotes: 1