У меня есть набор данных под названием «опрос» со строками отдельных идентификаторов и столбцами со многими вопросами. Мне нужно перекодировать значение в 1 столбце как NA
и переместить наблюдение в другой столбец.
Например:
ID Food Vegetable
aaa NA NA
bbb NA lemon
ccc NA sprout
ddd fruit NA
eee fruit NA
fff NA watermelon
Я хочу изменить наблюдения lemon
и watermelon
, принадлежащие ID bbb
и fff
, чтобы поместить их в столбец Food
и переименовать их fruit
(респонденты опроса поместили их в неправильный столбец) и оставить NA
позади в столбце vegetable
.
Выглядеть как:
ID Food Vegetable
aaa NA NA
bbb fruit NA
ccc NA sprout
ddd fruit NA
eee fruit NA
fff fruit NA
Я использовал:
survey<- survey %>%
mutate(food = if_else(str_detect(Vegetable,"(lemon)|(watermelon)"),"fruit", Food))
Который работает для преобразования NA
в fruit
в столбце food
, но не согласуется с NA
в столбце vegetable
, он также превращает все остальные фрукты в столбце food
в NA
!
ДАННЫЕ:
structure(list(ID = c("aaa", "bbb", "ccc", "ddd", "eee", "fff"
), Food = c(NA, NA, NA, "fruit", "fruit", NA), Vegetable = c(NA,
"lemon", "sprout", NA, NA, "watermelon")), class = "data.frame", row.names = c(NA,
-6L))
P.S.: Это продолжение предыдущего вопроса, который я задал, на который был дан ответ. Это не совсем тот же вопрос, что и раньше, поэтому я задал новый.
версия dplyr (1.0.2)
Один из вариантов — обновить Food
и Vegetable
в зависимости от того, являются ли значения Vegetable
%in%
заданным списком, not_vegetables
:
not_vegetables <- c("grape", "tomato")
df %>%
mutate(Food = if_else(Vegetable %in% not_vegetables, "fruit", Food),
Vegetable = if_else(Vegetable %in% not_vegetables, NA_character_, Vegetable))
Другой способ - replace
, across
оба столбца и сделать if_else
внутри:
df %>%
mutate(across(
c(Food, Vegetable),
~replace(.,
Vegetable %in% not_vegetables,
if_else(cur_column() == "Food", 'fruit', NA_character_))
))
К сожалению, ни один из них, похоже, не сработал? Первое решение запустилось, но никаких изменений в данных. второе решение дало ошибку: Error: Problem with `mutate()` input `..1`. x Formula shorthand must be wrapped in `where()`. # Bad data %>% select(~...) # Good data %>% select(where(~...)) ℹ Input `..1` is `across(...)`. Backtrace: >
Я протестировал оба локально перед публикацией, похоже на проблему с версией и / или что-то о том, как настроены ваши реальные данные. Какая у вас версия dplyr? across
был представлен в апреле. Можете ли вы отредактировать свой пост, чтобы включить dput
ваших данных или вашего игрушечного df? Так будет легче узнать, что происходит.
Как ни странно, когда я делаю это в новом файле R, он работает... возможно ли, что %in%
замаскирован другим пакетом?
Рад, что это сработало. Перемаскировка, может быть? Вы можете посмотреть на conflicts(detail=TRUE)
, чтобы увидеть, какие функции конфликтуют в вашей среде. Обратите внимание, что %in%
— это базовая функция R, я не думаю, что что-либо в tidyverse перезаписывает ее.
Используя базу R, вы могли бы попробовать это:
#Conditional
values <- c('grape','tomato')
df$Food <- ifelse(df$Vegetable %in% values,'fruit',df$Food)
df$Vegetable <- ifelse(df$Vegetable %in% values,NA,df$Vegetable)
Выход:
df
ID Food Vegetable
1 aaa fruit <NA>
2 bbb fruit <NA>
3 ccc fruit <NA>
4 ddd fruit <NA>
Данные
df <- structure(list(ID = c("aaa", "bbb", "ccc", "ddd"), Food = c(NA,
NA, "fruit", "fruit"), Vegetable = c("grape", "tomato", NA, NA
)), class = "data.frame", row.names = c(NA, -4L))
После шага вы можете сделать
mutate(Vegetable = NA_character_)