source

R 파이프 연산자 사용 시 조건부 평가 %>%

itover 2023. 6. 26. 23:01
반응형

R 파이프 연산자 사용 시 조건부 평가 %>%

파이프 오퍼레이터 사용 시%>%의 패지와같은키와 같은 dplyr,ggvis,dycharts등, 조건부로 단계를 수행하려면 어떻게 해야 합니까?를 들면 예를들어,어,

step_1 %>%
step_2 %>%

if(condition)
step_3

이러한 접근 방식은 효과가 없는 것 같습니다.

step_1 %>%
step_2 
if(condition) %>% step_3

step_1 %>%
step_2 %>%
if(condition) step_3

갈 길이 멉니다.

if(condition)
{
step_1 %>%
step_2 
}else{
step_1 %>%
step_2 %>%
step_3
}

중복이 없는 더 좋은 방법이 있습니까?

다음은 다음과 같은 이점을 활용하는 간단한 예입니다..그리고.ifelse:

X<-1
Y<-T

X %>% add(1) %>% { ifelse(Y ,add(.,1), . ) }

ifelse,한다면Y이라TRUE 1이 되고, 인 1 " 을그 추 가 할 경 않 으 마 면 값 지 반 을 환 합 니 다 막 지 렇 우 니 다 합 반 환 ▁if ▁return ▁the 값 ▁add ▁will ▁of ▁1 ▁value▁justX..는 체인의 이전 단계의 출력이 어디로 가는지 기능을 알려주는 스탠드인으로, 두 분기 모두에서 사용할 수 있습니다.

@BenBolker가 지적했듯이 편집은 원하지 않을 수 있습니다.ifelse에 그서여기에가 .if판본

X %>% 
add(1) %>% 
 {if(Y) add(.,1) else .}

@Frank가 제가 사용해야 한다고 지적해 주셔서 감사합니다.{내 주위의 교정기if그리고.ifelse체인을 계속하기 위한 진술.

편집:purrr::when(){purr} 버전 1.0.0에서 더 이상 사용되지 않습니다.

그런 경우가 있는 것 같습니다. 합이 25 미만이면 몇 개의 숫자를 합산하고, 그렇지 않으면 0을 반환합니다.


library("magrittr")
1:3 %>% 
  purrr::when(sum(.) < 25 ~ sum(.), ~0)
#> [1] 6

when첫 번째 유효 조건의 작업 결과 값을 반환합니다.조건을 왼쪽에 놓습니다.~그리고 그 오른쪽에 있는 행동.위에서는 한 가지 조건(그 다음에는 다른 경우)만 사용했지만 여러 가지 조건이 있을 수 있습니다.

당신은 그것을 더 긴 파이프에 쉽게 통합할 수 있습니다.

다음은 @John Paul이 제공한 답변의 변형입니다.은 이변은다사다니합용음을형▁the를 사용합니다.`if` if ... else ...진술.

library(magrittr)

X <- 1
Y <- TRUE

X %>% `if`(Y, . + 1, .) %>% multiply_by(2)
# [1] 4

이 경우에는 곱슬곱슬한 교정기가 필요하지 않습니다.`if`의 또는, 주변ifelse-에만 - 변에만해당if ... else ...진술.그러나 점 자리 표시자가 중첩 함수 호출에만 나타나는 경우, magritr은 기본적으로 왼쪽을 오른쪽의 첫 번째 인수로 연결합니다.이 동작은 식을 중괄호 모양으로 묶어서 재정의됩니다.이 두 체인의 차이점에 주목하십시오.

X %>% `if`(Y, . + 1, . + 2)
# [1] TRUE
X %>% {`if`(Y, . + 1, . + 2)}
# [1] 4

는 " ▁the▁call"에 두 번 모두 됩니다.`if` 수함, 후이부터. + 1그리고.. + 2는 로해됩니다로 됩니다.`+`(., 1)그리고.`+`(., 2)각각 다음과 같다.첫 은 그서첫번표다음같결은것반입다니는환하과의 결과를 입니다.`if`(1, TRUE, 1 + 1, 1 + 2)(충분히 이해합니다.`if`하지 않은 인수에 ), 두은 사용하지 않은 추가 인수에 대해 불평하지 않음, 두 번째 표현은 입니다.`if`(TRUE, 1 + 1, 1 + 2)이 경우 원하는 동작입니다.

Magritr 파이프 연산자가 점 자리 표시자를 처리하는 방법에 대한 자세한 내용은 다음에 대한 도움말 파일을 참조하십시오.%>%특히 "2차 목적을 위한 점 사용" 섹션.

파이프에서 조금 물러나는 것이 가장 쉬워 보입니다(다른 솔루션을 보고 싶긴 하지만). 예를 들어, 다음과 같습니다.

library("dplyr")
z <- data.frame(a=1:2)
z %>% mutate(b=a^2) -> z2
if (z2$b[1]>1) {
    z2 %>% mutate(b=b^2) -> z2
}
z2 %>% mutate(b=b^2) -> z3

이것은 @John Paul의 대답을 약간 수정한 것입니다(당신은 정말 원하지 않을 수도 있습니다).ifelse두 인수를 모두 평가하고 벡터화합니다.반품할 수 있도록 수정해주시면 감사하겠습니다..조건이 거짓인 경우 자동으로 ...(:이것이 효과가 있다고 생각하지만 실제로 테스트를 많이/생각해 본 적은 없습니다...)

iff <- function(cond,x,y) {
    if(cond) return(x) else return(y)
}

z %>% mutate(b=a^2) %>%
    iff(cond=z2$b[1]>1,mutate(.,b=b^2),.) %>%
 mutate(b=b^2) -> z4

좋아해요purrr::when은 모두 저는 좀 더에 기능을 했습니다.pif(파이프인 경우), 답변 끝에 있는 코드 및 문서를 참조하십시오.

수 됨) 이 " " " " " " ", " ", ", ", ", "일 경우 입력은 기본적으로 되지 않고 됩니다.FALSE.

다른 답변의 예에 사용됩니다.

## from Ben Bolker
data.frame(a=1:2) %>% 
  mutate(b=a^2) %>%
  pif(~b[1]>1, ~mutate(.,b=b^2)) %>%
  mutate(b=b^2)
#   a  b
# 1 1  1
# 2 2 16

## from Lorenz Walthert
1:3 %>% pif(sum(.) < 25,sum,0)
# [1] 6

## from clbieganek 
1 %>% pif(TRUE,~. + 1) %>% `*`(2)
# [1] 4

# from theforestecologist
1 %>% `+`(1) %>% pif(TRUE ,~ .+1)
# [1] 3

기타 예:

## using functions
iris %>% pif(is.data.frame, dim, nrow)
# [1] 150   5

## using formulas
iris %>% pif(~is.numeric(Species), 
             ~"numeric :)",
             ~paste(class(Species)[1],":("))
# [1] "factor :("

## using expressions
iris %>% pif(nrow(.) > 2, head(.,2))
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa

## careful with expressions
iris %>% pif(TRUE, dim,  warning("this will be evaluated"))
# [1] 150   5
# Warning message:
# In inherits(false, "formula") : this will be evaluated
iris %>% pif(TRUE, dim, ~warning("this won't be evaluated"))
# [1] 150   5

기능.

#' Pipe friendly conditional operation
#'
#' Apply a transformation on the data only if a condition is met, 
#' by default if condition is not met the input is returned unchanged.
#' 
#' The use of formula or functions is recommended over the use of expressions
#' for the following reasons :
#' 
#' \itemize{
#'   \item If \code{true} and/or \code{false} are provided as expressions they 
#'   will be evaluated wether the condition is \code{TRUE} or \code{FALSE}.
#'   Functions or formulas on the other hand will be applied on the data only if
#'   the relevant condition is met
#'   \item Formulas support calling directly a column of the data by its name 
#'   without \code{x$foo} notation.
#'   \item Dot notation will work in expressions only if `pif` is used in a pipe
#'   chain
#' }
#' 
#' @param x An object
#' @param p A predicate function, a formula describing such a predicate function, or an expression.
#' @param true,false Functions to apply to the data, formulas describing such functions, or expressions.
#'
#' @return The output of \code{true} or \code{false}, either as expressions or applied on data as functions
#' @export
#'
#' @examples
#'# using functions
#'pif(iris, is.data.frame, dim, nrow)
#'# using formulas
#'pif(iris, ~is.numeric(Species), ~"numeric :)",~paste(class(Species)[1],":("))
#'# using expressions
#'pif(iris, nrow(iris) > 2, head(iris,2))
#'# careful with expressions
#'pif(iris, TRUE, dim,  warning("this will be evaluated"))
#'pif(iris, TRUE, dim, ~warning("this won't be evaluated"))
pif <- function(x, p, true, false = identity){
  if(!requireNamespace("purrr")) 
    stop("Package 'purrr' needs to be installed to use function 'pif'")

  if(inherits(p,     "formula"))
    p     <- purrr::as_mapper(
      if(!is.list(x)) p else update(p,~with(...,.)))
  if(inherits(true,  "formula"))
    true  <- purrr::as_mapper(
      if(!is.list(x)) true else update(true,~with(...,.)))
  if(inherits(false, "formula"))
    false <- purrr::as_mapper(
      if(!is.list(x)) false else update(false,~with(...,.)))

  if ( (is.function(p) && p(x)) || (!is.function(p) && p)){
    if(is.function(true)) true(x) else true
  }  else {
    if(is.function(false)) false(x) else false
  }
}

가능한 해결책은 익명 함수를 사용하는 것입니다.

library(magrittr)
1 %>% 
  (\(.) if (T) . + 1 else .) %>% 
  multiply_by(2)

언급URL : https://stackoverflow.com/questions/30604107/r-conditional-evaluation-when-using-the-pipe-operator

반응형