Замена значений в столбцах фрейма данных на месте

#r #dplyr #tidyverse #tidyr #purrr

#r #dplyr #tidyverse #tidyr #муррр

Вопрос:

Я хочу заменить значения в определенных столбцах фрейма данных. Я могу сделать это один раз, но он перестает работать, как только я пытаюсь создать функцию. Я также хотел бы повторить функцию для подмножества всех столбцов, и я тоже не уверен, как это сделать.

Вот пример:

 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()
  

Я хочу поменять местами «Да» на «T» и «Нет» на «F» в Likes_pie и Likes_sunshine . Но я хочу указать эти два столбца и исключить Likes_friendship . Я хочу сохранить NA-s. Нет никаких значений, кроме «Да» и «Нет».

Можно обойтись одним столбцом:

 my.d = my.d %>% 
  mutate(
    Likes_pie = case_when(
      Likes_pie == 'Yes' ~ 'T',
      Likes_pie == 'No' ~ 'F'
    )
  )
  

Но это не работает в функции:

 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

  

Предполагая, что это так, как мне заменить значения столбцов для каждого столбца?
Является ли sg таким mutate_if(d, c('Likes_pie', 'Likes_sunshine'), function(x) nomConverter(x)) способом?

Комментарии:

1. Включен ли Likes_friendship один из столбцов my.d ?

2. да, это так. моя ошибка.

Ответ №1:

Решение с использованием lapply и ifelse . Я предполагаю Likes_friendship , что это один из столбцов (иначе зачем вы создали этот вектор?), Но находится ли столбец в фрейме данных, не влияет на эффективность этого решения.

Кстати T , and F — это зарезервированное слово в R, указывающее логическое значение TRUE и FALSE , соответственно. Символ "T" и "F" может привести других в замешательство.

 # 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     
  

ДАННЫЕ

 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()
  

Комментарии:

1. Если вы хотите ускорить его / иметь тонну данных и сохранить "T" и "F" как символы, вы также можете использовать lapply(my.d[cols], function(x) c("F", "T")[(x == "Yes") 1]) или, может быть, даже lapply(lapply(my.d[cols], `==`, "Yes"), as.character) . Я знаю, что скорость не была целью, я просто хотел добавить пару похожих решений 🙂

2. @Andrew Спасибо, что поделились. Эти два являются разумными решениями.

Ответ №2:

Не могли бы вы просто использовать 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
  

Или для определенных столбцов используйте mutate_at

 cols <- c("Likes_pie", "Likes_sunshine")
my.d %>%
    mutate_at(vars(cols), ~case_when(
        .x == "Yes" ~ "T",
        .x == "No" ~ "F",
        TRUE ~ .x))
  

дает тот же результат.

Ответ №3:

Вы могли бы использовать mutate_at() для этого один раз, an ifelse тоже будет делать то, что вы хотите:

 (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 
  

Ответ №4:

Если предполагается преобразовать в логический столбец, просто выполните ==

 library(dplyr)
my.d %>% 
   mutate_at(vars(cols),  list(~ . == "Yes"))
  

где

 cols <- c("Likes_pie", "Likes_sunshine")