@ fabian-werner가 제공하는 대답은 훌륭하지만 객체에는 여러 클래스가있을 수 있으며 "인자"가 반드시 첫 번째로 반환되는 class(yes)
것은 아니므로 모든 작은 클래스 속성을 확인하기 위해이 작은 수정을 제안합니다.
safe.ifelse <- function(cond, yes, no) {
class.y <- class(yes)
if ("factor" %in% class.y) { # Note the small condition change here
levels.y = levels(yes)
}
X <- ifelse(cond,yes,no)
if ("factor" %in% class.y) { # Note the small condition change here
X = as.factor(X)
levels(X) = levels.y
} else {
class(X) <- class.y
}
return(X)
}
또한 R 개발 팀과 함께 base :: ifelse ()가 보존 할 속성의 사용자 선택에 따라 속성을 유지하도록 문서화 된 옵션을 추가하라는 요청을 제출했습니다. 요청은 여기에 있습니다 : https://bugs.r-project.org/bugzilla/show_bug.cgi?id=16609- 그것은 항상 현재와 같은 방식으로 이미 "WONTFIX"로 표시되었습니다. 그러나 간단한 추가만으로도 많은 R 사용자의 두통을 줄일 수있는 이유에 대한 후속 논의를 제공했습니다. 아마도 해당 버그 스레드에서 "+1"은 R Core 팀이 다시 한 번 살펴볼 것을 권장합니다.
편집 : 다음은 "cond"(기본 ifelse () 동작), "yes", 위의 코드에 따른 동작 또는 "no"중 유지할 속성을 사용자가 지정할 수있는 더 나은 버전입니다. "아니오"값의 속성이 더 좋습니다.
safe_ifelse <- function(cond, yes, no, preserved_attributes = "yes") {
# Capture the user's choice for which attributes to preserve in return value
preserved <- switch(EXPR = preserved_attributes, "cond" = cond,
"yes" = yes,
"no" = no);
# Preserve the desired values and check if object is a factor
preserved_class <- class(preserved);
preserved_levels <- levels(preserved);
preserved_is_factor <- "factor" %in% preserved_class;
# We have to use base::ifelse() for its vectorized properties
# If we do our own if() {} else {}, then it will only work on first variable in a list
return_obj <- ifelse(cond, yes, no);
# If the object whose attributes we want to retain is a factor
# Typecast the return object as.factor()
# Set its levels()
# Then check to see if it's also one or more classes in addition to "factor"
# If so, set the classes, which will preserve "factor" too
if (preserved_is_factor) {
return_obj <- as.factor(return_obj);
levels(return_obj) <- preserved_levels;
if (length(preserved_class) > 1) {
class(return_obj) <- preserved_class;
}
}
# In all cases we want to preserve the class of the chosen object, so set it here
else {
class(return_obj) <- preserved_class;
}
return(return_obj);
} # End safe_ifelse function
if_else()
dplyr 패키지 에는 이제ifelse
Date 클래스의 올바른 클래스를 유지하면서 대체 할 수 있는 함수가 있습니다.이 함수 는 아래 에 최근 답변으로 게시되어 있습니다 . (이 의견으로) 앞서 언급 한 많은 다른 답변과 달리 CRAN 패키지로 단위 테스트되고 문서화 된 기능을 제공 하여이 문제를 해결함에 따라 여기에주의를 기울입니다.