Reputation: 535
I want to replace values in certain columns in a data frame. I can do it once but it stops working once I try to build a function. I'd also like to repeat the function on a subset of all columns and I'm not sure how to do that either.
Here's an example:
library(tidyverse)
Kid = c('Alfie', 'Brenda', 'Charlie', 'Dalma')
Likes_pie = c('Yes', 'Yes', 'No', NA)
Likes_sunshine = c(NA, 'Yes', 'Yes', 'No')
Likes_friendship = c('Yes', NA, 'Yes', 'No')
my.d = cbind(Kid, Likes_pie, Likes_sunshine) %>% as_tibble()
I want to swop "Yes" to "T" and "No" to "F" in Likes_pie
and Likes_sunshine
. But I want to specify these two columns and leave out Likes_friendship
. I want to preserve NA-s. There are no values besides "Yes" and "No".
Can do with one column:
my.d = my.d %>%
mutate(
Likes_pie = case_when(
Likes_pie == 'Yes' ~ 'T',
Likes_pie == 'No' ~ 'F'
)
)
But this doesn't work in a function:
valConverter = function(d, var.value){
d = d %>%
mutate(
var.value = case_when(
var.value == 'Yes' ~ 'T',
var.value == 'No' ~ 'F'
)
)
return(d)
}
my.d = valConverter(my.d, Likes_sunshine)
my.d$Likes_pie
my.d$Likes_sunshine # :E
Assuming it did, how would I replace the column values for each column?
Is sg like mutate_if(d, c('Likes_pie', 'Likes_sunshine'), function(x) nomConverter(x))
the way to go?
Upvotes: 3
Views: 155
Reputation: 887971
If the intention is to convert to logical column, just do ==
library(dplyr)
my.d %>%
mutate_at(vars(cols), list(~ . == "Yes"))
where
cols <- c("Likes_pie", "Likes_sunshine")
Upvotes: 2
Reputation: 39184
A solution using lapply
and ifelse
. I assume Likes_friendship
is one of the columns (Otherwise, why did you create this vector?), but whether the column is in the data frame does not affect the effectiveness of this solution.
By the way T
and F
are reserved word in R indicating logical value TRUE
and FALSE
, respectively. The character "T"
and "F"
may make others confused.
# Store the column name you want to change
cols <- c("Likes_pie", "Likes_sunshine")
my.d[cols] <- lapply(my.d[cols], function(x) ifelse(x == "Yes", "T", "F"))
my.d
# # A tibble: 4 x 4
# Kid Likes_pie Likes_sunshine Likes_friendship
# <chr> <chr> <chr> <chr>
# 1 Alfie T NA Yes
# 2 Brenda T T NA
# 3 Charlie F T Yes
# 4 Dalma NA F No
DATA
library(tidyverse)
Kid = c('Alfie', 'Brenda', 'Charlie', 'Dalma')
Likes_pie = c('Yes', 'Yes', 'No', NA)
Likes_sunshine = c(NA, 'Yes', 'Yes', 'No')
Likes_friendship = c('Yes', NA, 'Yes', 'No')
my.d = cbind(Kid, Likes_pie, Likes_sunshine, Likes_friendship) %>% as_tibble()
Upvotes: 4
Reputation: 2959
You could use mutate_at()
to do this in one hit, an ifelse
will do what you want too:
(my.d <- tibble(Kid, Likes_pie, Likes_sunshine, Likes_friendship) %>%
mutate_at(c("Likes_pie", "Likes_sunshine"), list(~ifelse(. == "Yes", T, F))))
# A tibble: 4 x 4
Kid Likes_pie Likes_sunshine Likes_friendship
<chr> <lgl> <lgl> <chr>
1 Alfie TRUE NA Yes
2 Brenda TRUE TRUE NA
3 Charlie FALSE TRUE Yes
4 Dalma NA FALSE No
Upvotes: 2
Reputation: 50738
Couldn't you just use mutate_all
?
my.d %>%
mutate_all(~case_when(
.x == "Yes" ~ "T",
.x == "No" ~ "F",
TRUE ~ .x))
## A tibble: 4 x 3
# Kid Likes_pie Likes_sunshine
# <chr> <chr> <chr>
#1 Alfie T NA
#2 Brenda T T
#3 Charlie F T
#4 Dalma NA F
Or for specific columns use mutate_at
cols <- c("Likes_pie", "Likes_sunshine")
my.d %>%
mutate_at(vars(cols), ~case_when(
.x == "Yes" ~ "T",
.x == "No" ~ "F",
TRUE ~ .x))
giving the same result.
Upvotes: 2