Reputation: 2071
I have the following dataframe:
set.seed(1)
df <- data.frame(X1 = sample(c(letters[1:5],NA),10,replace=TRUE),
X2 = sample(c(letters[1:5],NA),10,replace=TRUE),
X3 = sample(c(letters[1:5],NA),10,replace=TRUE),
stringsAsFactors = FALSE)
X1 X2 X3
1 b b <NA>
2 c b b
3 d e d
4 <NA> c a
5 b e b
6 <NA> c c
7 <NA> e a
8 d <NA> c
9 d c <NA>
10 a e c
I want to replace a
for 5, b
for 4, c
for 3, d
for 2, and e
for 1, with:
df %>% lapply(., plyr::mapvalues(, c("a","b","c","d","e"), c(5,4,3,2,1)))
But it doesn't work: I get a warning that it's missing the first argument of the function mapvalues()
.
Does anyone know what I am doing wrong?
Upvotes: 1
Views: 426
Reputation: 11981
The syntax using lapply
is slightly different. Here is how it works:
df %>% lapply(plyr::mapvalues, from = c("a","b","c","d","e"), to = c(5,4,3,2,1))
$X1
[1] "1" "3" "3" "1" "1" "2" "4" "5" NA "2"
$X2
[1] "2" "1" NA "3" "1" "5" "3" "2" NA NA
$X3
[1] "3" "3" NA "1" NA "1" "1" "2" NA "2"
If you still want to have a dataframe afterwards it is better to use apply
instead of lapply
:
df %>% apply(2, plyr::mapvalues, from = c("a","b","c","d","e"), to = c(5,4,3,2,1)) %>%
as.data.frame(stringsAsFactors = F)
X1 X2 X3
1 4 4 <NA>
2 3 4 4
3 2 1 2
4 <NA> 3 5
5 4 1 4
6 <NA> 3 3
7 <NA> 1 5
8 2 <NA> 3
9 2 3 <NA>
10 5 1 3
Upvotes: 1
Reputation: 11514
A simple yet straightforward approach:
lookup <- 5:1
names(lookup) <- c("a","b","c","d","e")
df[] <- lapply(df, function(x) lookup[x])
df
X1 X2 X3
1 4 4 NA
2 3 4 4
3 2 1 2
4 NA 3 5
5 4 1 4
6 NA 3 3
7 NA 1 5
8 2 NA 3
9 2 3 NA
10 5 1 3
Note that lookup
is a simple named vector, i.e.
> lookup
a b c d e
5 4 3 2 1
And df[]
ensures that you keep the dataframe structure when you lapply
over it. Within the call to lapply
, the values in each column are simply used for a lookup by name in the lookup table. To highlight this, lookup["c"]
returns the value "3".
Upvotes: 1