Nice programing

dplyr 조건부 값으로 변경

nicepro 2020. 11. 24. 19:52
반응형

dplyr 조건부 값으로 변경


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하나요?


이 시도:

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

Update 1 Since originally posted dplyr has changed %.% to %>% so have modified answer accordingly.

Update 2 dplyr now has case_when which provides another solution:

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

With dplyr 0.7.2, you can use the very useful case_when function :

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)

Expressed with dplyr::mutate, it gives:

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

Please note that NA are not treated specially, as it can be misleading. The function will return NA only when no condition is matched. If you put a line with TRUE ~ ..., like I did in my example, the return value will then never be NA.

Therefore, you have to expressively tell case_when to put NA where it belongs by adding a statement like is.na(x$V1) | is.na(x$V3) ~ NA_integer_. Hint: the dplyr::coalesce() function can be really useful here sometimes!

Moreover, please note that NA alone will usually not work, you have to put special NA values : NA_integer_, NA_character_ or NA_real_.


It looks like derivedFactor from the mosaic package was designed for this. In this example, it would look something like:

library(mosaic)
myfile <- mutate(myfile, V5 = derivedFactor(
    "1" = (V1==1 & V2!=4),
    "2" = (V2==4 & V3!=1),
    .method = "first",
    .default = 0
    ))

(If you want the outcome to be numeric instead of a factor, wrap the derivedFactor with an as.numeric.)

Note that the .default option combined with .method = "first" sets the "else" condition -- this approach is described in the help file for derivedFactor.

참고URL : https://stackoverflow.com/questions/22337394/dplyr-mutate-with-conditional-values

반응형