R 데이터 프레임에서 'Inf' 값 정리
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
사용할 수 있습니다.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))
상당히 빠른 속도입니다.
na_if() 함수를 사용한 applyr/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)))
[<-
와 함께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
hablar 패키지에는 이 문제에 대한 매우 간단한 해결책이 있습니다.
library(hablar)
dat %>% rationalize()
모든 Inf가 포함된 데이터 프레임을 반환하는 데이터 프레임은 NA로 변환됩니다.
위의 일부 솔루션과 비교한 타이밍입니다.코드: 라이브러리(hablar) 라이브러리(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,.))
아답터 파이프 체인 안에서 이 작업을 수행할 수 있습니다.
%>% mutate_all(.,.funs = function(x){ifelse(is.infinite(x),NA,x)}) %>%
저는 그것이 간단하고 우아하며 빠르다고 생각합니다.
이미 많은 답이 있지만, 저를 위해 이것을 추가하고 싶습니다.tidyverse
솔루션은 항상 잘 작동했습니다.
%>% mutate_all(function(x) ifelse(is.nan(x) | is.infinite(x), NA, x)) %>%
다른 솔루션:
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
또한 Infs의 좌표가 필요한 경우 다음 작업을 수행할 수 있습니다.
library(rlist)
list.clean(apply(df, 2, function(x){which(is.infinite(x))}), function(x) length(x) == 0L, TRUE)
결과:
$colname1
[1] row1 row2 ...
$colname2
[2] row1 row2 ...
이 정보를 사용하여 특정 위치의 Inf 값을 원하는 평균, 중위수 또는 측정 시스템으로 바꿀 수 있습니다.
예를 들어 (원소 01의 경우):
repInf = list.clean(apply(df, 2, function(x){which(is.infinite(x))}), function(x) length(x) == 0L, TRUE)
df[repInf[[1]], names(repInf)[[1]]] = median or mean(is.finite(df[ ,names(repInf)[[1]]]), na.rm = TRUE)
반복:
for (nonInf in 1:length(repInf)) {
df[repInf[[nonInf]], names(repInf)[[nonInf]]] = mean(is.finite(df[ , names(repInf)[[nonInf]]]))
}
끼어들어, 이게 잘 된 줄 알았어요.
infNanReplace <- function (v, r = 0) {
v[!is.finite(v)] <- r
return(v)
}
handy replace_na 함수 https://tidyr.tidyverse.org/reference/replace_na.html 도 사용할 수 있습니다.
언급URL : https://stackoverflow.com/questions/12188509/cleaning-inf-values-from-an-r-dataframe
'programing' 카테고리의 다른 글
ID 열이 있는 SqlBulkCopy 삽입 (0) | 2023.07.05 |
---|---|
선택 쿼리에 대한 최적의 가져오기 크기를 확인하는 방법 (0) | 2023.06.30 |
데이터베이스에서 문자열 일부 검색 및 바꾸기 (0) | 2023.06.30 |
일부 사용자 지정 예약 제품 유형에 대해 "세금 제로" 요금 설정 (0) | 2023.06.30 |
Spring @ConditionalOnProperty, 누락된 경우에만 일치시키는 방법 (0) | 2023.06.30 |