Объединить мутировать с условными значениями


в большом фрейме данных ("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?

3 54

3 ответа:

попробуйте это:

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 изменился %.% до %>% так изменили ответ соответственно.

обновление 2 dplyr и case_when, который предлагает другое решение:

myfile %>% 
       mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, 
                             V2 == 4 & V3 != 1 ~ 2,
                             TRUE ~ 0))

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

обратите внимание: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.)

отметим, что в сочетании с .method = "first" устанавливает условие "else" -- этот подход описан в файле справки для derivedFactor.