petyar
petyar

Reputation: 535

Replacing values in columns in a dataframe in situ

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

Answers (4)

akrun
akrun

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

www
www

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

Paul
Paul

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

Maurits Evers
Maurits Evers

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

Related Questions