dplyr 조건부 값으로 변경


87

4 개의 열이있는 큰 데이터 프레임 ( "myfile")에서 처음 4 개의 열을 기준으로 조건부 값이있는 다섯 번째 열을 추가해야합니다.

주로 큰 데이터 세트의 속도 때문에 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?


V1..4가 모두 정수 (요인, 논리, 문자열 또는 부동이 아님)인지 여부를 나타내는 것이 유용합니까? NA, ( NaN, +Inf, -Inf)를 올바르게 처리하는 데 관심이 있습니까?
smci

속도가 선호하는 문제인 것 같으면 dplyr사용하는 것이 좋습니다 data.table.
Valentin

답변:


105

이 시도:

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

두 번째 해결책을 시도했습니다. 이 오류가 발생했습니다 : Error in mutate_impl (.data, named_dots (...), environment ()) : REAL ()은 '논리적'이 아닌 '숫자'에만 적용될 수 있습니다. 무슨 일이 일어나는지 알고 있습니까?
rdatasculptor

5
나는하지 둥지에 당신을 수있는 방법을 발견 ifelse: 문myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, 0), V5 = ifelse(V2 == 4 & V3 != 1, 2, V5))
알렉스

31

와 함께 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합니다 . 힌트 :이 기능은 때때로 여기에서 정말 유용 할 수 있습니다!NAis.na(x$V1) | is.na(x$V3) ~ NA_integer_dplyr::coalesce()

또한 NA일반적으로 단독으로 작동하지 않으므로 특수 NA값 을 입력해야 합니다 : NA_integer_, NA_character_또는 NA_real_.


1
이것은 파생 팩터보다 훨씬 빠릅니다.
Fato39

12

그것은처럼 보이는 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"이 접근 방식에 대한 도움말 파일에 설명되어 있습니다 - 설정은 "다른"조건 derivedFactor.


.asFactor = F옵션을 사용하거나 derivedVariable동일한 패키지에서 (유사한) 기능 을 사용 하여 결과가 요인이되는 것을 방지 할 수도 있습니다 .
Jake Fisher

그것은처럼 보이는 recodedplyr 0.5이 작업을 수행합니다에서. 나는 그것을 아직 조사하지 않았다. blog.rstudio.org/2016/06/27/dplyr-0-5-0
Jake Fisher

이것은 1e6 행이있는 데이터의 경우 느 렸습니다.
Fato39

3
@ Fato39 예, mosaic::derivedFactor기능 군은 매우 느립니다. 그 이유를 알고 있다면 그것에 대한 나의 질문에 답해주십시오 : stackoverflow.com/questions/33787691/… . 다른 댓글에서 dplyr::case_when더 빠른 것을 보게되어 기쁩니다 . 전환해야합니다.
Jake Fisher

다음 명령을 시도하고 있습니다 .library (mosaic) VENEZ.FINAL2 <-mutate (VENEZ, SEX = derivedFactor ( "M"= (CATEGORY == "BULL"& CATEGORY! = "SIRE"), "F"= ( CATEGORY == "COW"& CATEGORY! = "HEIFER"), .method = "first", .default = "NA")) 작동하지 않습니다. VENEZ.FINAL2 조건 만 해결하십시오. <-mutate (VENEZ, SEX = derivedFactor ( "M"= (CATEGORY == "BULL 도와 주실 수 있나요? 감사합니다!
Johanna Ramirez
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.