Замените значения в одном столбце, взяв значения из другого столбца

#r #tidyverse

Вопрос:

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

У меня есть такой фрейм данных (реальный df результат удаления дублированных строк)

 df <- data.frame(name1 = c("a" , "b", "c", "a"),
                 name2 = c("x", NA, NA, NA),
                 name3 = c(NA, "b1", "c1", NA),
                 name4 = c("x", "b1", "c1", "a"))

  name1 name2 name3 name4
1     a     x  <NA>     x
2     b  <NA>    b1    b1
3     c  <NA>    c1    c1
4     a  <NA>  <NA>     a
 

Можем ли мы заменить a на x вызов, если значение в name4 столбце совпадает со name1 столбцом?

Я не хочу использовать и назначать x непосредственно здесь, так как в моих данных должно быть много подобных случаев. Есть какие-нибудь предложения для меня, пожалуйста? (использование base-R также подходит для меня, так как я хотел бы узнать больше)

Желаемый результат

   name1 name2 name3 name4
1     a     x  <NA>     x
2     b  <NA>    b1    b1
3     c  <NA>    c1    c1
4     a  <NA>  <NA>     x
 

Мое объяснение стола и мои ожидания:

У меня есть 3 столбца name1, name2, name3 (после удаления дублированных строк). Столбец Name4-это последний столбец, содержащий значение, которое я хочу получить из 3 предыдущих столбцов. Значение в столбце name2 является моим первым приоритетом для использования, затем значение в столбце name3.

В моей четвертой строке, поскольку значение NA отображается в столбце name2, я взял «a» из столбца name1. Я думаю о том, могу ли я заменить a на x без присвоения x, т. е. Если значение (т. е. a) в имени 4 == значение (т. Е. a) в имени 1, то a в имени 4 заменено на x в имени 2 или 4.

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

1. Означает ли «x», которое вы не хотите явно использовать, что оно взято из столбца name2 в строке, где у name1 есть «a»? Я не понимаю, что бы ты хотел сделать

2. Извините, я думаю, что собью людей с толку, я закрою и задам еще один более ясный вопрос.

3. Вы не должны удалять вопрос, на который многие пользователи уже потратили время, чтобы дать вам ответ. Вместо этого вам следует улучшить свой вопрос, отредактировав его.

4. Вы все еще не ответили на вопрос в комментариях. Откуда берется x значение (если оно не должно быть жестко закодировано)? Какой логике должна следовать восстановительная стоимость?

5. итак, давайте с самого начала скажем, что у меня есть 3 столбца name1, name2, name3 (после удаления дублированных строк). Столбец Name4-это последний столбец, содержащий значение, которое я хочу получить из 3 предыдущих столбцов. Значение в столбце name2 является моим первым приоритетом для использования, затем значение в столбце name3

Ответ №1:

Ваши критерии для определения name4 , как я понимаю, это:

  1. Используйте name2 из той же строки, если она доступна
  2. Используйте name3 из той же строки, если она доступна
  3. Оставьте это без внимания (на данный момент)
  4. Заполните пропущенные name4 значения name4 значениями из предыдущих строк, которые имеют одинаковое name1 значение.

Если вам нужно решение на основе tidyverse:

 library(dplyr)
library(tidyr)

df <- data.frame(name1 = c("a" , "b", "c", "a"),
                 name2 = c("x", NA, NA, NA),
                 name3 = c(NA, "b1", "c1", NA))

result <- df %>% 
  mutate(name4 = case_when(
    #!is.na(name4) ~ name4, # when name4 is not missing, use it? If you like...
    !is.na(name2) ~ name2, # when name2 is not missing, use it
    !is.na(name3) ~ name3, # when name3 is not missing, use it
    TRUE ~ NA_character_   # leave a NA for now otherwise
  )) %>%
  group_by(name1) %>%
  fill(name4, .direction = c("down")) %>% # Fill each group looking at the previous non-missing row.
  ungroup()

 

ВОЗВРАТ:

 # A tibble: 4 × 4
  name1 name2 name3 name4
  <chr> <chr> <chr> <chr>
1 a     x     NA    x    
2 b     NA    b1    b1   
3 c     NA    c1    c1   
4 a     NA    NA    x   
 

Обратите внимание, что fill можно заполнять в нескольких направлениях, вы можете использовать «вниз», если хотите сначала заполнить сверху вниз, а затем снизу вверх.

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

1. большое вам спасибо, многое понятно. Однако я понял, что, поскольку столбец name4 уже существовал, значения NA будут указаны даже для имени, которое я хочу сохранить в столбце name4.

2. Главная проблема, с которой мы все сталкиваемся, — это понять, каковы ваши требования, ваши критерии, что вы хотите сделать. Лучшее, что вы можете сделать, — это улучшить свой вопрос и уточнить, что вам нужно сделать. Я попытался объяснить требования, которые я понял из вашего вопроса в своем ответе, но они были неправильными. Не могли бы вы скопировать мой первоначальный абзац/список критериев и изменить его, чтобы он делал то, что вы ожидаете (как обрабатывать существующий столбец name4)? Тогда нам будет намного проще помочь вам найти решение, которое вы хотите.

Ответ №2:

Вы можете сгруппировать по name1 и, если name1 и name4 равны, заменить name4 значение на 1-е доступное значение, отличное от NA.

 library(dplyr)

df %>%
  group_by(name1) %>%
  mutate(name4 = ifelse(name1 == name4, na.omit(unlist(cur_data()))[1], name4)) %>%
  ungroup

# name1 name2 name3 name4
#  <chr> <chr> <chr> <chr>
#1 a     x     NA    x    
#2 b     NA    b1    b1   
#3 c     NA    c1    c1   
#4 a     NA    NA    x    
 

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

1. код хорошо работал для моих воспроизводимых данных, но он не будет работать для моих данных :(. значение осталось прежним после запуска кода

2. Вы назначили вывод обратно в фрейм данных? df <- df %>% group_by(name1) ... ?

3. это хорошо сработало, чувак. Однако, что делать, если у меня есть еще один столбец между столбцами name1 и name2. Так как, если бы у меня был этот столбец, код не работал бы.

4. Если вы хотите выбрать значения только из определенного столбца, вы можете изменить na.omit(unlist(cur_data()))[1] его на na.omit(unlist(select(cur_data(), name1, name2)))[1]

5. Я только что понял, что мне также нужно, чтобы столбец name3 работал как столбец name2. Если name1 == имя 4, то возьмите значение из name3, чтобы заменить значение в name4 (как указано выше). Но теперь имя 1 будет содержать некоторое значение NA. Я попробовал еще раз над кодом, но теперь это выглядело странно. Можете ли вы взглянуть на это, пожалуйста

Ответ №3:

Ты можешь сделать это вот так:

 df[which(df$name1==df$name4), "name4"] <- "x"
 

В основном это означает, что в вашем фрейме данных вы выбираете строки , в которых name1 == name4 и name4 столбец, а затем меняете эти значения на «x».

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

1. Или аналогично: df$name4[df$name1 == df$name4] <- "x" (просто дело вкуса)

2. да, но здесь мы называем точное число x. Я не хочу использовать его здесь. С тех пор, что, если у меня будет много дел.

3. Пожалуйста, поясните, что вы имеете в виду. Предлагаемое решение приводит к результату, о котором вы упомянули

4. Я уже обновил свой комментарий выше, пожалуйста, взгляните на него.

Ответ №4:

Базовое ifelse решение R:

 df$name4 <- ifelse(df$name1 == df$name4, "x", df$name4)
 

Основываясь на вашем обновлении, используя dplyr first :

 library(dplyr)

df$name4 <- ifelse(df$name1 == df$name4, first(df$name4), df$name4)
 

Это делает следующее:

  • Проверяет, равно ли имя 1 имени 4
  • Если name1 равно name4, оно заменяет значение name4 первым значением, встречающимся для name4.

Результат:

   name1 name2 name3 name4
1     a     x  <NA>     x
2     b  <NA>    b1    b1
3     c  <NA>    c1    c1
4     a  <NA>  <NA>     x
 

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

1. Я попробовал, но это не сработало бы, так как он автоматически создал много дублированных строк в столбце name4 для моих реальных данных со значением на основе name1 (т. Е. a)