Пытаюсь найти путь dplyr
канонический к mutate
a tibble
по номеру строки.
Я рассмотрел много вопросов о переполнении стека и проблем с GH, таких функций, как row_number
, if_else
, case_when
, но до сих пор не ясно, как правильно добиться следующего.
Минимальный пример: имея data.frame, я хотел бы обновить один из его столбцов до определенного значения (здесь NA
) для определенных строк, указав индексы строк (здесь строки 2 и 4).
Обновляемый столбец не должен быть параметризован, а только номера строк.
Ниже базы R для достижения следующего.
DF = data.frame(x=5:1)
idx = c(2L, 4L)
DF[idx, "x"] = NA_integer_
DF
# x
#1 5
#2 NA
#3 3
#4 NA
#5 1
replace
это базовая функция R, тогда это путь dplyr? есть также if_else
альтернатива
Нет ничего плохого в том, чтобы использовать базовую функцию R внутри функции dplyr, и я не могу представить, как нет может использовать базовые функции R, даже если по какой-то причине вы хотели это сделать.
Кроме того, хакерский вариант DF %>% mutate(x = 'is.na<'(x, idx))
@camille дело не в том, чтобы не использовать базовую функцию R в dplyr, а в том, чтобы знать канонический способ, который dplyr предлагает для достижения следующего. Как я подчеркнул в вопросе.
Я говорю, что нет ничего плохого в том, что @akrun предлагает с replace
, просто потому, что это базовая функция, она все еще должна работать. Вы также можете использовать что-то вроде mutate(x = ifelse(row_number() %in% idx, NA_integer_, x))
, чтобы заменить x только в этих номерах строк.
Иногда кажется, что должна быть функция mutate_when
, не так ли? Хотя я не знаю, есть ли он. Решение @camille if_else
— это именно то, что я собирался порекомендовать; Я думаю, что это настолько близко, насколько мы собираемся подойти к каноническому.
@camille спасибо, ваш row_number()
подход выглядит аккуратно. Если бы я пошел по пути R, я бы выбрал просто TB=as_tibble(DF); TB[idx, "x"] = NA_integer_
Вау @akrun! Мне нужна гифка с открытым ртом. Это восхитительно! Я полностью узнал что-то новое здесь, и искренне благодарю вас. Я изменил свой комментарий, так как он все еще находился в 5-минутном окне. Тогда я бы определенно рекомендовал решение base-R, и я думаю, что люди из RStudio / Tidyverse тоже!
@akrun, DF %>% mutate(x = 'is.na<'(x, idx))
выдает "Ошибка оценки: не удалось найти функцию "is.na<"", не могли бы вы проверить?
@Artem Я использую обратные кавычки, но здесь для комментариев я сделал одинарную кавычку
Основываясь на отзывах @camille и согласии других комментаторов, самый аккуратный код — это mutate(x = ifelse(row_number() %in% idx, NA_integer_, x))
.
КСТАТИ. Лучше использовать <-
вместо =
присвоений и избегать использования заглавных букв в именах объектов. Для получения дополнительной информации см. Руководство по стилю tidyverse
Итак, полный код:
library(dplyr)
df <- data.frame(x = 5:1)
idx <- c(2L, 4L)
df %>% mutate(x = ifelse(row_number() %in% idx, NA_integer_, x))
# x
#1 5
#2 NA
#3 3
#4 NA
#5 1
<-
vs =
— это предмет предпочтения стиля, ни один из них не лучше. На самом деле <-
имеет недостаток, заключающийся в том, что простое пространство меняет значение оператора присваивания на меньшее, чем унарный минус, подробнее об этом см.: github.com/Rdatatable/data.table/issues/…Хотя ваш ответ - это самый аккуратный способ добиться того, что я задал в вопросе, я не думаю, что его следует рекомендовать. Базовый способ R также работает с табличками, и IMO следует отдавать предпочтение. Принятие ответа, поскольку вопрос касался аккуратного способа. Он добавляет дополнительные накладные расходы на память, как показано на моих последних слайдах, поэтому требует больше памяти, чем базовый способ R: raw.githubusercontent.com/wiki/Rdatatable/data.table/talks/…
Можно ли использовать
DF %>% mutate(x = replace(x, idx, NA))