R Inf
에는 데이터 프레임을 변환 할 때 일부 값 을 생성하는 작업이 있습니다.
이러한 Inf
가치를 NA
가치 로 바꾸고 싶습니다 . 내가 가진 코드는 대용량 데이터의 경우 느립니다. 더 빠른 방법이 있습니까?
다음 데이터 프레임이 있다고 가정합니다.
dat <- data.frame(a=c(1, Inf), b=c(Inf, 3), d=c("a","b"))
다음은 단일 경우에서 작동합니다.
dat[,1][is.infinite(dat[,1])] = NA
그래서 다음 루프로 일반화했습니다.
cf_DFinf2NA <- function(x)
{
for (i in 1:ncol(x)){
x[,i][is.infinite(x[,i])] = NA
}
return(x)
}
그러나 나는 이것이 실제로 R의 힘을 사용하고 있다고 생각하지 않습니다.
답변
옵션 1
a data.frame
가 열 목록 이라는 사실을 사용한 다음을 사용 do.call
하여 data.frame
.
do.call(data.frame,lapply(DT, function(x) replace(x, is.infinite(x),NA)))
옵션 2- data.table
당신은 사용할 수 data.table
및 set
. 이것은 내부 복사를 방지합니다.
DT <- data.table(dat)
invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA)))
또는 열 번호 사용 (열이 많은 경우 더 빠름) :
for (j in 1:ncol(DT)) set(DT, which(is.infinite(DT[[j]])), j, NA)
타이밍
# some `big(ish)` data
dat <- data.frame(a = rep(c(1,Inf), 1e6), b = rep(c(Inf,2), 1e6),
c = rep(c('a','b'),1e6),d = rep(c(1,Inf), 1e6),
e = rep(c(Inf,2), 1e6))
# create data.table
library(data.table)
DT <- data.table(dat)
# replace (@mnel)
system.time(na_dat <- do.call(data.frame,lapply(dat, function(x) replace(x, is.infinite(x),NA))))
## user system elapsed
# 0.52 0.01 0.53
# is.na (@dwin)
system.time(is.na(dat) <- sapply(dat, is.infinite))
# user system elapsed
# 32.96 0.07 33.12
# modified is.na
system.time(is.na(dat) <- do.call(cbind,lapply(dat, is.infinite)))
# user system elapsed
# 1.22 0.38 1.60
# data.table (@mnel)
system.time(invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA))))
# user system elapsed
# 0.29 0.02 0.31
data.table
가장 빠릅니다. 사용하면 sapply
눈에 띄게 속도가 느려집니다.
답변
사용 sapply
및is.na<-
> dat <- data.frame(a=c(1, Inf), b=c(Inf, 3), d=c("a","b"))
> is.na(dat) <- sapply(dat, is.infinite)
> dat
a b d
1 1 NA a
2 NA 3 b
또는 사용할 수 있습니다 (편집 인 @mnel에 크레딧 제공),
> is.na(dat) <- do.call(cbind,lapply(dat, is.infinite))
훨씬 빠릅니다.
답변
[<-
과는 mapply
조금 빠르게보다 sapply
.
> dat[mapply(is.infinite, dat)] <- NA
mnel의 데이터를 사용하면 타이밍이
> system.time(dat[mapply(is.infinite, dat)] <- NA)
# user system elapsed
# 15.281 0.000 13.750
답변
다음은 na_if () 함수를 사용하는 dplyr / tidyverse 솔루션입니다 .
dat %>% mutate_if(is.numeric, list(~na_if(., Inf)))
이것은 양의 무한대를 NA로만 대체합니다. 음의 무한대 값도 교체해야하는 경우 반복해야합니다.
dat %>% mutate_if(is.numeric, list(~na_if(., Inf))) %>%
mutate_if(is.numeric, list(~na_if(., -Inf)))
답변
hablar 패키지에는이 문제에 대한 매우 간단한 해결책이 있습니다.
library(hablar)
dat %>% rationalize()
모든 Inf가있는 데이터 프레임을 반환하는 것은 NA로 변환됩니다.
위의 일부 솔루션과 비교 한 타이밍입니다. 코드 : library (hablar) library (data.table)
dat <- data.frame(a = rep(c(1,Inf), 1e6), b = rep(c(Inf,2), 1e6),
c = rep(c('a','b'),1e6),d = rep(c(1,Inf), 1e6),
e = rep(c(Inf,2), 1e6))
DT <- data.table(dat)
system.time(dat[mapply(is.infinite, dat)] <- NA)
system.time(dat[dat==Inf] <- NA)
system.time(invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA))))
system.time(rationalize(dat))
결과:
> system.time(dat[mapply(is.infinite, dat)] <- NA)
user system elapsed
0.125 0.039 0.164
> system.time(dat[dat==Inf] <- NA)
user system elapsed
0.095 0.010 0.108
> system.time(invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA))))
user system elapsed
0.065 0.002 0.067
> system.time(rationalize(dat))
user system elapsed
0.058 0.014 0.072
>
data.table이 hablar보다 빠릅니다. 그러나 더 긴 구문이 있습니다.
답변
Feng Mai는 부정적이고 긍정적 인 무한대를 얻기 위해 위의 깔끔한 대답을 가지고 있습니다.
dat %>% mutate_if(is.numeric, list(~na_if(., Inf))) %>%
mutate_if(is.numeric, list(~na_if(., -Inf)))
이것은 잘 작동하지만, 찬성 주석에서 제안 된 것처럼 한 번에 두 줄을 모두 수행하기 위해 여기에서 abs (.)를 바꾸지 않는 것이 경고의 말씀입니다. 작동하는 것처럼 보이지만 데이터 세트의 모든 음수 값을 양수로 변경합니다! 다음으로 확인할 수 있습니다.
data(iris)
#The last line here is bad - it converts all negative values to positive
iris %>%
mutate_if(is.numeric, ~scale(.)) %>%
mutate(infinities = Sepal.Length / 0) %>%
mutate_if(is.numeric, list(~na_if(abs(.), Inf)))
한 줄의 경우 다음과 같이 작동합니다.
mutate_if(is.numeric, ~ifelse(abs(.) == Inf,NA,.))
답변
또 다른 해결책 :
dat <- data.frame(a = rep(c(1,Inf), 1e6), b = rep(c(Inf,2), 1e6),
c = rep(c('a','b'),1e6),d = rep(c(1,Inf), 1e6),
e = rep(c(Inf,2), 1e6))
system.time(dat[dat==Inf] <- NA)
# user system elapsed
# 0.316 0.024 0.340
