ifelse()가 Date 개체를 숫자 개체로 변환하지 않도록 방지하는 방법
는 기을사용있다니습 을 하고 있습니다.ifelse()
날짜 벡터를 조작합니다.나는 그 결과가 수업이 될 것이라고 예상했습니다.Date
놀랐습니다.numeric
대신 벡터를 사용합니다.다음은 예입니다.
dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))
dates <- ifelse(dates == '2011-01-01', dates - 1, dates)
str(dates)
이것은 전체 벡터에 걸쳐 연산을 수행하면 다음을 반환하기 때문에 특히 놀라운 일입니다.Date
물건.
dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04','2011-01-05'))
dates <- dates - 1
str(dates)
다른 기능을 사용하여 수술을 해야 합니까?Date
벡터? 만약 어떤 이 있습니까?그렇다면 어떤 기능이 있습니까?그렇지 않은 경우 어떻게 강제로ifelse
입력과 동일한 유형의 벡터를 반환하시겠습니까?
의 ifelse
버그가 아니라 기능임을 나타내지만, 저는 여전히 제가 발견한 놀라운 행동에 대한 설명을 찾는 데 어려움을 겪고 있습니다.
사용할 수 있습니다.data.table::fifelse
(data.table >= 1.12.3
) 또는dplyr::if_else
.
data.table::fifelse
와는과 다르게 .
ifelse
,fifelse
입력 유형 및 클래스를 보존합니다.
library(data.table)
dates <- fifelse(dates == '2011-01-01', dates - 1, dates)
str(dates)
# Date[1:5], format: "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"
dplyr::if_else
릴리스 정보에서:
[
if_else
있는 ] 보 엄 격 있 가 습 니 고 다 지ifelse()
그자리의true
그리고.false
인수는 동일한 형식이어야 합니다.이는 덜 놀라운 반환 유형을 제공하며, S3 벡터를 날짜처럼 보존합니다."
library(dplyr)
dates <- if_else(dates == '2011-01-01', dates - 1, dates)
str(dates)
# Date[1:5], format: "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"
문서화된 가치와 관련이 있습니다.ifelse
:
및"길이와속차동벡일터한포및함이성원차▁dim(벡터)포▁of함▁
class
") 로서test
의 값으 값얻 습니 의 값에서 데이터 을 구합니다.yes
또는no
답변 모드는 논리적으로 강제되어 우선 다음 값을 모두 수용합니다.yes
그 에 리고나어떤값취하든에서 .no
.
그 의미를 요약하면,ifelse
요인은 수준을 잃게 되고 날짜는 클래스를 잃게 되며 모드("숫자")만 복원됩니다.대신 사용해 보십시오.
dates[dates == '2011-01-01'] <- dates[dates == '2011-01-01'] - 1
str(dates)
# Date[1:5], format: "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"
다음을 생성할 수 있습니다.safe.ifelse
:
safe.ifelse <- function(cond, yes, no){ class.y <- class(yes)
X <- ifelse(cond, yes, no)
class(X) <- class.y; return(X)}
safe.ifelse(dates == '2011-01-01', dates - 1, dates)
# [1] "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"
다음 참고 사항:해들리가 집을 지었군요if_else
결과 클래스를 보존하는 magritr/dplyr/dplyr 패키지의 magritr/dplyr 복합체로 변환합니다.
DWin의 설명은 정확합니다.저는 이것을 가지고 잠시 동안 장난을 치고 싸웠으며, 그 후에 제가 단순히 수업을 강요할 수 있다는 것을 깨달았습니다.
dates <- as.Date(c('2011-01-01','2011-01-02','2011-01-03','2011-01-04','2011-01-05'))
dates <- ifelse(dates=='2011-01-01',dates-1,dates)
str(dates)
class(dates)<- "Date"
str(dates)
처음에 이것은 저에게 약간 "해킹"처럼 느껴졌습니다.하지만 지금은 그저 ifelse()로부터 받는 성과 수익에 대한 작은 대가라고 생각합니다.게다가 여전히 루프보다 훨씬 더 간결합니다.
이것이 작동하지 않는 이유는 ifelse() 함수가 값을 요인으로 변환하기 때문입니다.평가하기 전에 문자로 변환하는 것이 좋습니다.
dates <- as.Date(c('2011-01-01','2011-01-02','2011-01-03','2011-01-04','2011-01-05'))
dates_new <- dates - 1
dates <- as.Date(ifelse(dates =='2011-01-01',as.character(dates_new),as.character(dates)))
이것은 기본 R 외에 어떤 라이브러리도 필요하지 않습니다.
제안된 방법은 요인 열에서 사용할 수 없습니다.저는 이 개선을 제안하고 싶습니다.
safe.ifelse <- function(cond, yes, no) {
class.y <- class(yes)
if (class.y == "factor") {
levels.y = levels(yes)
}
X <- ifelse(cond,yes,no)
if (class.y == "factor") {
X = as.factor(X)
levels(X) = levels.y
} else {
class(X) <- class.y
}
return(X)
}
그건 그렇고, 안 그러면...큰 힘을 가지면 책임감이 커집니다. 즉, 1x1 행렬 및/또는 숫자(예를 들어 추가해야 할 때)의 유형 변환은 괜찮지만 이러한 유형 변환은 분명히 원하지 않습니다.나는 지금 다른 아이들의 똑같은 '버그'를 여러 번 마주쳤고 그것은 내 시간을 계속 훔칩니다 :-(
FW
@fabian-werner가 제공한 답변은 훌륭하지만 객체는 여러 클래스를 가질 수 있으며 "factor"가 반환된 첫 번째 클래스가 아닐 수 있습니다.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)
}
저는 또한 보존할 속성의 사용자 선택에 따라 base::ifelse()가 속성을 보존하도록 문서화된 옵션을 추가해 달라는 요청을 R 개발 팀에 제출했습니다.요청은 여기에 있습니다: https://bugs.r-project.org/bugzilla/show_bug.cgi?id=16609 - 현재와 같은 방식이라는 이유로 이미 "WONTFIX"로 플래그가 지정되었지만, 간단한 추가로 많은 R 사용자의 두통을 줄일 수 있는 이유에 대한 후속 주장을 제공했습니다.아마도 그 버그 스레드에 있는 당신의 "+1"이 R Core 팀이 다시 보도록 격려할 것입니다.
편집: 사용자가 "초"(기본 ifelse() 동작), "예", 위의 코드에 따른 동작 또는 "아니오" 값의 속성이 더 나은 경우 "아니오" 중에서 보존할 속성을 지정할 수 있는 더 나은 버전은 다음과 같습니다.
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
여기서 인덱싱을 사용하는 것이 어떻습니까?
> dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))
> dates[dates == '2011-01-01'] <- NA
> str(dates)
Date[1:5], format: NA "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"
언급URL : https://stackoverflow.com/questions/6668963/how-to-prevent-ifelse-from-turning-date-objects-into-numeric-objects
'programing' 카테고리의 다른 글
판다의 데카르트 제품 (0) | 2023.06.19 |
---|---|
깃이 색을 갖도록 Mac OS X 용어를 구성하는 방법은 무엇입니까? (0) | 2023.06.19 |
하위 클래스의 WordPress ajax 함수 (0) | 2023.06.19 |
exec()가 프로그램 이미지를 변경한 후 mallocated 메모리는 어떻게 됩니까? (0) | 2023.06.19 |
전체 폴더를 리포지토리에 재귀적으로 추가 (0) | 2023.06.19 |