В большом фрейме данных («myfile») с четырьмя столбцами мне нужно добавить пятый столбец со значениями, условно основанными на первых четырех столбцах.
Предпочитайте ответы с dplyr
и mutate
, главным образом из-за его скорости в больших наборах данных.
Мой фрейм данных выглядит так:
V1 V2 V3 V4
1 1 2 3 5
2 2 4 4 1
3 1 4 1 1
4 4 5 1 3
5 5 5 5 4
...
Значения пятого столбца (V5) основаны на некоторых условных правилах:
if (V1==1 & V2!=4) {
V5 <- 1
} else if (V2==4 & V3!=1) {
V5 <- 2
} else {
V5 <- 0
}
Теперь я хочу использовать эту mutate
функцию для использования этих правил во всех строках (чтобы избежать медленных циклов). Примерно так (и да, я знаю, что так не работает!):
myfile <- mutate(myfile, if (V1==1 & V2!=4){V5 = 1}
else if (V2==4 & V3!=1){V5 = 2}
else {V5 = 0})
Должен быть результат:
V1 V2 V3 V4 V5
1 1 2 3 5 1
2 2 4 4 1 2
3 1 4 1 1 0
4 4 5 1 3 0
5 5 5 5 4 0
Как это сделать dplyr
?
NA
, (NaN, +Inf, -Inf
)?dplyr
, я лучше воспользуюсь еюdata.table
.Ответы:
Попробуй это:
myfile %>% mutate(V5 = (V1 == 1 & V2 != 4) + 2 * (V2 == 4 & V3 != 1))
давая:
V1 V2 V3 V4 V5 1 1 2 3 5 1 2 2 4 4 1 2 3 1 4 1 1 0 4 4 5 1 3 0 5 5 5 5 4 0
или это:
myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, ifelse(V2 == 4 & V3 != 1, 2, 0)))
давая:
V1 V2 V3 V4 V5 1 1 2 3 5 1 2 2 4 4 1 2 3 1 4 1 1 0 4 4 5 1 3 0 5 5 5 5 4 0
Заметка
Предложите вам лучше назвать фрейм данных. myfile создает впечатление, что он содержит имя файла.
Выше использовали этот ввод:
myfile <- structure(list(V1 = c(1L, 2L, 1L, 4L, 5L), V2 = c(2L, 4L, 4L, 5L, 5L), V3 = c(3L, 4L, 1L, 1L, 5L), V4 = c(5L, 1L, 1L, 3L, 4L )), .Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c("1", "2", "3", "4", "5"))
Обновление 1 Поскольку первоначально опубликованный dplyr был изменен
%.%
на%>%
соответствующий ответ.Теперь у dplyr есть обновление 2 ,
case_when
которое предлагает другое решение:myfile %>% mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, V2 == 4 & V3 != 1 ~ 2, TRUE ~ 0))
источник
ifelse
утверждения:myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, 0), V5 = ifelse(V2 == 4 & V3 != 1, 2, V5))
С помощью
dplyr 0.7.2
вы можете использовать очень полезнуюcase_when
функцию:x=read.table( text="V1 V2 V3 V4 1 1 2 3 5 2 2 4 4 1 3 1 4 1 1 4 4 5 1 3 5 5 5 5 4") x$V5 = case_when(x$V1==1 & x$V2!=4 ~ 1, x$V2==4 & x$V3!=1 ~ 2, TRUE ~ 0)
Выражаясь с помощью
dplyr::mutate
, это дает:x = x %>% mutate( V5 = case_when( V1==1 & V2!=4 ~ 1, V2==4 & V3!=1 ~ 2, TRUE ~ 0 ) )
Обратите внимание, что
NA
не обрабатываются специально, так как могут ввести в заблуждение. Функция вернетсяNA
только в том случае, если ни одно условие не выполнено. Если вы поместите строку сTRUE ~ ...
, как я сделал в моем примере, возвращаемого значения никогда не будетNA
.Таким образом, вы должны сказать выразительнее
case_when
поставить ,NA
где она принадлежит, добавив такое заявлениеis.na(x$V1) | is.na(x$V3) ~ NA_integer_
. Подсказка:dplyr::coalesce()
функция иногда может быть здесь действительно полезной!Кроме того, обратите внимание , что в
NA
одиночку, как правило , не работают, вы должны поставить специальныеNA
значения:NA_integer_
,NA_character_
илиNA_real_
.источник
Похоже,
derivedFactor
изmosaic
упаковки было предназначено для этого. В этом примере это будет выглядеть примерно так:library(mosaic) myfile <- mutate(myfile, V5 = derivedFactor( "1" = (V1==1 & V2!=4), "2" = (V2==4 & V3!=1), .method = "first", .default = 0 ))
(Если вы хотите, чтобы результат был числовым, а не множителем,
derivedFactor
заключите в скобкуas.numeric
.)Обратите внимание, что
.default
опция в сочетании с.method = "first"
устанавливает условие «else» - этот подход описан в файле справки дляderivedFactor
.источник
.asFactor = F
опцию или (аналогичную)derivedVariable
функцию в том же пакете.recode
dplyr 0.5 это сделает. Однако я еще не исследовал это. См. Blog.rstudio.org/2016/06/27/dplyr-0-5-0mosaic::derivedFactor
семейство функций очень медленное. Если вы выясните, почему, ответьте на мой ТАК вопрос об этом: stackoverflow.com/questions/33787691/… . Я рад видеть из вашего другого комментария, чтоdplyr::case_when
это быстрее - мне придется переключиться на это.