NA를 최신 비NA 값으로 대체
data.frame(또는)data.table값에 를 ".), 이전의비앞하 NA 값을 "로작성으고싶습"입니다.벡터를 사용하는 간단한 예(대신)data.frame은과 같은뜻이 있습니다.
> y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
기능을 원합니다.fill.NAs()가 것은내건수있해줍다니게할설그가다를 구성할 수 .yy다음과 같은 경우:
> yy
[1] NA NA NA 2 2 2 2 3 3 3 4 4
의 (총 최대 소형 크기의 소총형여대(에 1Tb) ▁for▁many▁operation▁(▁this▁i합▁sized다니▁need여▁repeattotal러tb▁to야반▁small총복1해▁~(소해▁tb))에 대해 이 작업을 반복해야 합니다.data.frame인 경우 s(~30-50Mb)입니다.그 문제에 접근하는 좋은 방법은 무엇입니까?
내가 만든 추악한 해결책은 다음과 같은 기능을 사용합니다.
last <- function (x){
x[length(x)]
}
fill.NAs <- function(isNA){
if (isNA[1] == 1) {
isNA[1:max({which(isNA==0)[1]-1},1)] <- 0 # first is NAs
# can't be forward filled
}
isNA.neg <- isNA.pos <- isNA.diff <- diff(isNA)
isNA.pos[isNA.diff < 0] <- 0
isNA.neg[isNA.diff > 0] <- 0
which.isNA.neg <- which(as.logical(isNA.neg))
if (length(which.isNA.neg)==0) return(NULL) # generates warnings later, but works
which.isNA.pos <- which(as.logical(isNA.pos))
which.isNA <- which(as.logical(isNA))
if (length(which.isNA.neg)==length(which.isNA.pos)){
replacement <- rep(which.isNA.pos[2:length(which.isNA.neg)],
which.isNA.neg[2:max(length(which.isNA.neg)-1,2)] -
which.isNA.pos[1:max(length(which.isNA.neg)-1,1)])
replacement <- c(replacement, rep(last(which.isNA.pos), last(which.isNA) - last(which.isNA.pos)))
} else {
replacement <- rep(which.isNA.pos[1:length(which.isNA.neg)], which.isNA.neg - which.isNA.pos[1:length(which.isNA.neg)])
replacement <- c(replacement, rep(last(which.isNA.pos), last(which.isNA) - last(which.isNA.pos)))
}
replacement
}
수fill.NAs는 다음과 같이 사용됩니다.
y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
isNA <- as.numeric(is.na(y))
replacement <- fill.NAs(isNA)
if (length(replacement)){
which.isNA <- which(as.logical(isNA))
to.replace <- which.isNA[which(isNA==0)[1]:length(which.isNA)]
y[to.replace] <- y[replacement]
}
산출량
> y
[1] NA 2 2 2 2 3 3 3 4 4 4
효과가 있을 것 같습니다.하지만, 친구, 그것은 못생겼나요?좋은 의견이라도 있나?
당신은 아마도 사용하기를 원할 것입니다.na.locf()사용자의 NA 값을 대체하기 위해 마지막 관찰을 진행할 수 있는 기능을 동물원 패키지에서 제공합니다.
다음은 도움말 페이지의 사용 예입니다.
library(zoo)
az <- zoo(1:6)
bz <- zoo(c(2,NA,1,4,5,2))
na.locf(bz)
1 2 3 4 5 6
2 2 1 4 5 2
na.locf(bz, fromLast = TRUE)
1 2 3 4 5 6
2 1 1 4 5 2
cz <- zoo(c(NA,9,3,2,3,2))
na.locf(cz)
2 3 4 5 6
9 3 2 3 2
오래된 질문을 꺼내 죄송합니다.기차 안에서 이 일을 할 수 있는 기능을 찾을 수 없어서 제가 직접 작성했습니다.
저는 그것이 조금 더 빠르다는 것을 알게 되어 자랑스러웠습니다.
하지만 유연성이 떨어집니다.
하지만 그것은 잘 작동합니다.ave그게 제가 필요로 했던 것입니다.
repeat.before = function(x) { # repeats the last non NA value. Keeps leading NA
ind = which(!is.na(x)) # get positions of nonmissing values
if(is.na(x[1])) # if it begins with a missing, add the
ind = c(1,ind) # first position to the indices
rep(x[ind], times = diff( # repeat the values at these indices
c(ind, length(x) + 1) )) # diffing the indices + length yields how often
} # they need to be repeated
x = c(NA,NA,'a',NA,NA,NA,NA,NA,NA,NA,NA,'b','c','d',NA,NA,NA,NA,NA,'e')
xx = rep(x, 1000000)
system.time({ yzoo = na.locf(xx,na.rm=F)})
## user system elapsed
## 2.754 0.667 3.406
system.time({ yrep = repeat.before(xx)})
## user system elapsed
## 0.597 0.199 0.793
편집
의 가장 있는 대답이 때문에, 저는 제했습니다. 저는 이것제가많답되면이서투, 저는동이동필원물때요하제기자상자것다켰니습시기주기않문에을신의사는다는능하지을용종물종원의이가한표장이▁zoo'▁i▁as,,▁need▁i다니상습켰▁because시기▁became▁i▁function자▁my▁own▁most▁often주것▁this▁reminded▁my▁up▁that을▁answers▁oftenvoted는않다▁was저,이것는이는지maxgap. 수 + 때가 있어서 하기 위해 .제가 debug를 할 수 없는 plyr + date를 사용했을 때 동물원은 엣지 케이스에 이상한 문제가 있어서, 저는 예전의 기능을 향상시키기 위해 오늘 이것으로 돌아왔습니다.
저는 향상된 기능과 여기에 있는 다른 모든 항목을 벤치마킹했습니다.은, 기본기집경우의합능,,tidyr::fill가장 빠르면서도 에지 케이스를 실패하지 않습니다.@더 입력 이 없습니다는 @BrandonBertelsen의 Rcpp에 대한 를 잘못 했습니다).all.equal).
이 필한경우가 필요하다면.maxgap아래의 제 기능은 동물원보다 빠릅니다(그리고 날짜에 이상한 문제가 없습니다).
저는 제 시험 서류를 올렸습니다.
신기능
repeat_last = function(x, forward = TRUE, maxgap = Inf, na.rm = FALSE) {
if (!forward) x = rev(x) # reverse x twice if carrying backward
ind = which(!is.na(x)) # get positions of nonmissing values
if (is.na(x[1]) && !na.rm) # if it begins with NA
ind = c(1,ind) # add first pos
rep_times = diff( # diffing the indices + length yields how often
c(ind, length(x) + 1) ) # they need to be repeated
if (maxgap < Inf) {
exceed = rep_times - 1 > maxgap # exceeding maxgap
if (any(exceed)) { # any exceed?
ind = sort(c(ind[exceed] + 1, ind)) # add NA in gaps
rep_times = diff(c(ind, length(x) + 1) ) # diff again
}
}
x = rep(x[ind], times = rep_times) # repeat the values at these indices
if (!forward) x = rev(x) # second reversion
x
}
저는 또한 이전 패키지(Github만 해당)에 그 기능을 넣었습니다.
a data.table솔루션:
dt <- data.table(y = c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA))
dt[, y_forward_fill := y[1], .(cumsum(!is.na(y)))]
dt
y y_forward_fill
1: NA NA
2: 2 2
3: 2 2
4: NA 2
5: NA 2
6: 3 3
7: NA 3
8: 4 4
9: NA 4
10: NA 4
이 접근 방식은 순방향 채우기 0에서도 작동할 수 있습니다.
dt <- data.table(y = c(0, 2, -2, 0, 0, 3, 0, -4, 0, 0))
dt[, y_forward_fill := y[1], .(cumsum(y != 0))]
dt
y y_forward_fill
1: 0 0
2: 2 2
3: -2 -2
4: 0 -2
5: 0 -2
6: 3 3
7: 0 3
8: -4 -4
9: 0 -4
10: 0 -4
은 규모에 수 유용하게 됩니다. 순방향 는 방 규 와 순 채 별 수 를 위 이 유 합 니 용 다 매 우 서 에 치 기 우 향 방 할 행 룹 그 법 은 터 모 가 큰 데 이 ▁with ( ▁this ▁by ▁and ▁trivial ▁at 합 니 이 다 ▁becomes ▁scale 용 ▁group ▁method ▁where s ▁on ▁is 이는 다음과 같습니다.data.table을룹에니다에 만 하면 .by 의 절cumsum
dt <- data.table(group = sample(c('a', 'b'), 20, replace = TRUE), y = sample(c(1:4, rep(NA, 4)), 20 , replace = TRUE))
dt <- dt[order(group)]
dt[, y_forward_fill := y[1], .(group, cumsum(!is.na(y)))]
dt
group y y_forward_fill
1: a NA NA
2: a NA NA
3: a NA NA
4: a 2 2
5: a NA 2
6: a 1 1
7: a NA 1
8: a 3 3
9: a NA 3
10: a NA 3
11: a 4 4
12: a NA 4
13: a 1 1
14: a 4 4
15: a NA 4
16: a 3 3
17: b 4 4
18: b NA 4
19: b NA 4
20: b 2 2
당신은 할 수 .data.tablenafill 있수는에서 할 수 있습니다.data.table >= 1.12.3.
library(data.table)
nafill(y, type = "locf")
# [1] NA 2 2 2 2 3 3 4 4 4
가 터가다 경우열인에 data.table또한 참조를 통해 업데이트할 수 있습니다.setnafill:
d <- data.table(x = 1:10, y)
setnafill(d, type = "locf", cols = "y")
d
# x y
# 1: 1 NA
# 2: 2 2
# 3: 3 2
# 4: 4 2
# 5: 5 2
# 6: 6 3
# 7: 7 3
# 8: 8 4
# 9: 9 4
# 10: 10 4
가지고 계신다면,NA여러 열에...
d <- data.table(x = c(1, NA, 2), y = c(2, 3, NA), z = c(4, NA, 5))
# x y z
# 1: 1 2 4
# 2: NA 3 NA
# 3: 2 NA 5
...참고 자료를 한 번에 작성할 수 있습니다.
setnafill(d, type = "locf")
d
# x y z
# 1: 1 2 4
# 2: 1 3 4
# 3: 2 3 5
참고:
현재 이중 및 정수 데이터 유형만 [
data.table 1.12.6지원됩니다.
이 기능은 곧 확장될 것입니다. 미해결 문제 nafill을 참조하고 문자, 요인 및 기타 유형에 대한 setnafill을 참조하십시오. 여기서 임시 해결 방법도 찾을 수 있습니다.
그tidyr패키의(부일)의 )tidyverse패키지 제품군)에는 다음과 같은 간단한 방법이 있습니다.
y = c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
# first, transform it into a data.frame
df = as.data.frame(y)
y
1 NA
2 2
3 2
4 NA
5 NA
6 3
7 NA
8 4
9 NA
10 NA
library(tidyr)
fill(df, y, .direction = 'down')
y
1 NA
2 2
3 2
4 2
5 2
6 3
7 3
8 4
9 4
10 4
내 모자 던지기:
library(Rcpp)
cppFunction('IntegerVector na_locf(IntegerVector x) {
int n = x.size();
for(int i = 0; i<n; i++) {
if((i > 0) && (x[i] == NA_INTEGER) & (x[i-1] != NA_INTEGER)) {
x[i] = x[i-1];
}
}
return x;
}')
기본 샘플 및 벤치마크 설정:
x <- sample(c(1,2,3,4,NA))
bench_em <- function(x,count = 10) {
x <- sample(x,count,replace = TRUE)
print(microbenchmark(
na_locf(x),
replace_na_with_last(x),
na.lomf(x),
na.locf(x),
repeat.before(x)
), order = "mean", digits = 1)
}
몇 가지 벤치마크를 실행합니다.
bench_em(x,1e6)
Unit: microseconds
expr min lq mean median uq max neval
na_locf(x) 697 798 821 814 821 1e+03 100
na.lomf(x) 3511 4137 5002 4214 4330 1e+04 100
replace_na_with_last(x) 4482 5224 6473 5342 5801 2e+04 100
repeat.before(x) 4793 5044 6622 5097 5520 1e+04 100
na.locf(x) 12017 12658 17076 13545 19193 2e+05 100
만일의 경우:
all.equal(
na_locf(x),
replace_na_with_last(x),
na.lomf(x),
na.locf(x),
repeat.before(x)
)
[1] TRUE
갱신하다
숫자 벡터의 경우 함수가 약간 다릅니다.
NumericVector na_locf_numeric(NumericVector x) {
int n = x.size();
LogicalVector ina = is_na(x);
for(int i = 1; i<n; i++) {
if((ina[i] == TRUE) & (ina[i-1] != TRUE)) {
x[i] = x[i-1];
}
}
return x;
}
빅데이터 볼륨을 처리할 때, 우리는 더 효율적으로 하기 위해 data.table 패키지를 사용할 수 있습니다.
require(data.table)
replaceNaWithLatest <- function(
dfIn,
nameColNa = names(dfIn)[1]
){
dtTest <- data.table(dfIn)
setnames(dtTest, nameColNa, "colNa")
dtTest[, segment := cumsum(!is.na(colNa))]
dtTest[, colNa := colNa[1], by = "segment"]
dtTest[, segment := NULL]
setnames(dtTest, "colNa", nameColNa)
return(dtTest)
}
이것은 나에게 효과가 있었습니다.
replace_na_with_last<-function(x,a=!is.na(x)){
x[which(a)[c(1,1:sum(a))][cumsum(a)+1]]
}
> replace_na_with_last(c(1,NA,NA,NA,3,4,5,NA,5,5,5,NA,NA,NA))
[1] 1 1 1 1 3 4 5 5 5 5 5 5 5 5
> replace_na_with_last(c(NA,"aa",NA,"ccc",NA))
[1] "aa" "aa" "aa" "ccc" "ccc"
속도도 합리적입니다.
> system.time(replace_na_with_last(sample(c(1,2,3,NA),1e6,replace=TRUE)))
user system elapsed
0.072 0.000 0.071
선도적인NA약간 구김살이 있지만, 앞에 나오는 용어가 빠지지 않을 때 LOCF를 수행하는 매우 읽기 쉬운(그리고 벡터화된) 방법은 다음과 같습니다.
na.omit(y)[cumsum(!is.na(y))]
약간 덜 읽기 쉬운 수정은 일반적으로 작동합니다.
c(NA, na.omit(y))[cumsum(!is.na(y))+1]
원하는 출력을 제공합니다.
c(NA, 2, 2, 2, 2, 3, 3, 4, 4, 4)
이 기능을 사용해 보십시오.ZOO 패키지가 필요하지 않습니다.
# last observation moved forward
# replaces all NA values with last non-NA values
na.lomf <- function(x) {
na.lomf.0 <- function(x) {
non.na.idx <- which(!is.na(x))
if (is.na(x[1L])) {
non.na.idx <- c(1L, non.na.idx)
}
rep.int(x[non.na.idx], diff(c(non.na.idx, length(x) + 1L)))
}
dim.len <- length(dim(x))
if (dim.len == 0L) {
na.lomf.0(x)
} else {
apply(x, dim.len, na.lomf.0)
}
}
예:
> # vector
> na.lomf(c(1, NA,2, NA, NA))
[1] 1 1 2 2 2
>
> # matrix
> na.lomf(matrix(c(1, NA, NA, 2, NA, NA), ncol = 2))
[,1] [,2]
[1,] 1 2
[2,] 1 2
[3,] 1 2
다양한 패키지가 제공됩니다.na.locf(NA마지막 관찰 이월) 기능:
xts-xts::na.locfzoo-zoo::na.locfimputeTS-imputeTS::na.locfspacetime-spacetime::na.locf
또한 이 기능의 이름이 다른 다른 패키지도 있습니다.
Brandon Bertelsen (Rcpp)은 Rcpp을 의미합니다.저에게는 Numeric Vector 버전이 작동하지 않았습니다. 첫 번째 NA만 대체했습니다.는 이유는그 때문입니다.ina벡터는 함수의 시작 부분에서 한 번만 평가됩니다.
대신 IntegerVector 함수와 동일한 방법을 사용할 수 있습니다.다음은 저에게 효과가 있었습니다.
library(Rcpp)
cppFunction('NumericVector na_locf_numeric(NumericVector x) {
R_xlen_t n = x.size();
for(R_xlen_t i = 0; i<n; i++) {
if(i > 0 && !R_finite(x[i]) && R_finite(x[i-1])) {
x[i] = x[i-1];
}
}
return x;
}')
CharacterVector 버전이 필요한 경우에도 동일한 기본 접근 방식을 사용할 수 있습니다.
cppFunction('CharacterVector na_locf_character(CharacterVector x) {
R_xlen_t n = x.size();
for(R_xlen_t i = 0; i<n; i++) {
if(i > 0 && x[i] == NA_STRING && x[i-1] != NA_STRING) {
x[i] = x[i-1];
}
}
return x;
}')
@AdamO의 솔루션을 수정했습니다.이것은 더 빨리 달립니다. 왜냐하면 그것은 그것을 우회하기 때문입니다.na.omit기능.이 작업은 다음을 덮어씁니다.NA 터 의 값y (선行) )NA
z <- !is.na(y) # indicates the positions of y whose values we do not want to overwrite
z <- z | !cumsum(z) # for leading NA's in y, z will be TRUE, otherwise it will be FALSE where y has a NA and TRUE where y does not have a NA
y <- y[z][cumsum(z)]
를 사용하는 다음 솔루션을 .runner알크랜 패키지.
library(runner)
y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
fill_run(y, FALSE)
[1] NA 2 2 2 2 3 3 4 4 4
패키지 전체가 최적화되어 있으며 주요 내용은 cpp로 작성되었습니다.따라서 뛰어난 효율성을 제공합니다.
fill.NAs <- function(x) {is_na<-is.na(x); x[Reduce(function(i,j) if (is_na[j]) i else j, seq_len(length(x)), accumulate=T)]}
fill.NAs(c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA))
[1] NA 2 2 2 2 3 3 4 4 4
축소는 유사한 작업에 유용할 수 있는 훌륭한 기능적 프로그래밍 개념입니다.불행게에도그것배은다 ~보다 ~70배 .repeat.before상기의 회답에서
저는 개인적으로 이 기능을 사용합니다.나는 그것이 얼마나 빠르고 느리는지 모릅니다.하지만 그것은 도서관을 사용하지 않고도 제 역할을 합니다.
replace_na_with_previous<-function (vector) {
if (is.na(vector[1]))
vector[1] <- na.omit(vector)[1]
for (i in 1:length(vector)) {
if ((i - 1) > 0) {
if (is.na(vector[i]))
vector[i] <- vector[i - 1]
}
}
return(vector)
}
만약 당신이 이 기능을 데이터 프레임에 적용하고 싶다면, 당신의 데이터 프레임이 df라고 불리는 경우, 간단히.
df[]<-lapply(df,replace_na_with_previous)
질문과 유사한 문제를 가진 다른 사람들에게 도움이 될 수 있기 때문에 이 글을 올립니다.
최근의 가장최의근▁thetidyverse를사한솔션을 vctrs는 패지를다결수있다습니합할과음키▁can와 결합할 수 .mutate합니다.
library(dplyr)
library(magrittr)
library(vctrs)
as.data.frame(y) %>%
mutate(y_filled = vec_fill_missing(y, direction = c("down")) )
돌아온다
y y_filled
1 NA NA
2 2 2
3 2 2
4 NA 2
5 NA 2
6 3 3
7 NA 3
8 4 4
9 NA 4
10 NA 4
방향을 '채움 방향'으로 '채움 방향'으로 바꿔줍니다.'up'결과:
y y_filled
1 NA 2
2 2 2
3 2 2
4 NA 3
5 NA 3
6 3 3
7 NA 4
8 4 4
9 NA NA
10 NA NA
시도해 보고 싶을 수도 있습니다."downup"또는"updown"
이 솔루션은 아직 실험 수명 주기 중이므로 구문이 변경될 수 있습니다.
다음을 시도했습니다.
nullIdx <- as.array(which(is.na(masterData$RequiredColumn)))
masterData$RequiredColumn[nullIdx] = masterData$RequiredColumn[nullIdx-1]
nullIdx는 masterData$RequiredColumn이 Null/NA 값을 가질 때마다 idx 번호를 가져옵니다.다음 행에서는 이 값을 해당 Idx-1 값, 즉 각 NULL/NA 앞의 마지막 양호한 값으로 바꿉니다.
다른 제안보다 더 효율적인지는 모르겠지만 저에게는 효과가 있었습니다.
rollForward <- function(x){
curr <- 0
for (i in 1:length(x)){
if (is.na(x[i])){
x[i] <- curr
}
else{
curr <- x[i]
}
}
return(x)
}
파티에 너무 늦었지만, 사용하기에 매우 간결하고 확장 가능한 답변입니다.library(data.table) 따서로사수할있다습니용라▁as로 사용할 수 .dt[,SomeVariable:= FunctionBellow, by = list(group)].
library(imputeTS)
y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
y
[1] NA 2 2 NA NA 3 NA 4 NA NA
imputeTS::na_locf(imputeTS::na_locf(y,option = "nocb"),option="locf")
[1] 2 2 2 3 3 3 4 4 4 4
@Montgomery-Clift 및 @AdamO의 답변에서 파생된 기본 옵션은 의 값을 최신 값이NA 아닌 값으로 대체하는 것일 수 있습니다.
y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
i <- c(TRUE, !is.na(y[-1]))
y[i][cumsum(i)]
# [1] NA 2 2 2 2 3 3 4 4 4
개 안 될 때.NA새 벡터를 생성하는 대신 최신 비 NA 값으로 덮어쓸 수 있습니다.
fillNaR <- function(y) {
i <- which(is.na(y[-1]))
j <- which(diff(c(-1L,i)) > 1)
k <- diff(c(j, length(i) + 1))
i <- rep(i[j], k)
`[<-`(y, i + sequence(k), y[i])
}
fillNaR(y)
# [1] NA 2 2 2 2 3 3 4 4 4
속도가 중요한 경우 루프의 마지막 비-NA 값을 전파하는 루프는 RCPP를 사용하여 작성할 수 있습니다.입력 유형을 유연하게 사용하려면 템플릿을 사용하여 이 작업을 수행할 수 있습니다.
Rcpp::sourceCpp(code=r"(
#include <Rcpp.h>
using namespace Rcpp;
template <int RTYPE>
Vector<RTYPE> FNA(const Vector<RTYPE> y) {
auto x = clone(y); //or overwrite original
LogicalVector isNA = is_na(x);
size_t i = 0;
while(isNA[i] && i < x.size()) ++i;
for(++i; i < x.size(); ++i) if(isNA[i]) x[i] = x[i-1];
return x;
}
// [[Rcpp::export]]
RObject fillNaC(RObject x) {
RCPP_RETURN_VECTOR(FNA, x);
}
)")
fillNaC(y)
# [1] NA 2 2 2 2 3 3 4 4 4
은 이한기능내사수있다니습용할부서에러은 안에서 사용할 수.lapply의 모든 열에 그것들을 적용하는 것.data.frame.
DF[] <- lapply(DF, fillNaC)
데이터 유형에 특화된 Rcpp를 사용하는 다른 답변은 다음과 같이 보이지만 입력 벡터도 업데이트하고 있습니다.
y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
Rcpp::cppFunction("NumericVector fillNaCN(NumericVector x) {
for(auto i = x.begin()+1; i < x.end(); ++i) if(*i != *i) *i = *(i-1);
return x;
}")
fillNaCN(y)
# [1] NA 2 2 2 2 3 3 4 4 4
y
# [1] NA 2 2 2 2 3 3 4 4 4
벤치마크
fillNaR <- function(y) {
i <- which(is.na(y[-1]))
j <- which(diff(c(-1L,i)) > 1)
k <- diff(c(j, length(i) + 1))
i <- rep(i[j], k)
`[<-`(y, i + sequence(k), y[i])
}
Rcpp::sourceCpp(code=r"(
#include <Rcpp.h>
using namespace Rcpp;
template <int RTYPE>
Vector<RTYPE> FNA(const Vector<RTYPE> y) {
auto x = clone(y); //or overwrite original
LogicalVector isNA = is_na(x);
size_t i = 0;
while(isNA[i] && i < x.size()) ++i;
for(++i; i < x.size(); ++i) if(isNA[i]) x[i] = x[i-1];
return x;
}
// [[Rcpp::export]]
RObject fillNaC(RObject x) {
RCPP_RETURN_VECTOR(FNA, x);
}
)")
repeat.before <- function(x) { # @Ruben
ind = which(!is.na(x))
if(is.na(x[1])) ind = c(1,ind)
rep(x[ind], times = diff(c(ind, length(x) + 1) ))
}
RB2 <- function(x) {
ind = which(c(TRUE, !is.na(x[-1])))
rep(x[ind], diff(c(ind, length(x) + 1)))
}
MC <- function(y) { # @Montgomery Clift
z <- !is.na(y)
z <- z | !cumsum(z)
y[z][cumsum(z)]
}
MC2 <- function(y) {
z <- c(TRUE, !is.na(y[-1]))
y[z][cumsum(z)]
}
fill.NAs <- function(x) { # @Valentas
is_na <- is.na(x)
x[Reduce(function(i,j) if (is_na[j]) i else j, seq_len(length(x)), accumulate=T)]}
M <- alist(
fillNaR = fillNaR(y),
fillNaC = fillNaC(y),
repeat.before = repeat.before(y),
RB2 = RB2(y),
MC = MC(y),
MC2 = MC2(y),
fill.NAs = fill.NAs(y),
tidyr = tidyr::fill(data.frame(y), y)$y,
zoo = zoo::na.locf(y, na.rm=FALSE),
data.table = data.table::nafill(y, type = "locf"),
data.table2 = with(data.table::data.table(y)[, y := y[1], .(cumsum(!is.na(y)))], y),
imputeTS = imputeTS::na_locf(y, na_remaining = "keep"),
runner = runner::fill_run(y, FALSE),
vctrs = vctrs::vec_fill_missing(y, direction = "down"),
ave = ave(y, cumsum(!is.na(y)), FUN = \(x) x[1])
)
결과
n <- 1e5
set.seed(42); y <- rnorm(n); is.na(y) <- sample(seq_along(y), n/100)
bench::mark(exprs = M) #1% NA
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl>
# 1 fillNaR 399.82µs 1.02ms 459. 3.56MB 31.9 230 16
# 2 fillNaC 672.85µs 883.74µs 976. 1.15MB 22.0 488 11
# 3 repeat.before 1.28ms 2.8ms 290. 7.57MB 58.0 145 29
# 4 RB2 1.93ms 3.66ms 229. 9.86MB 57.7 115 29
# 5 MC 1.01ms 1.98ms 289. 5.33MB 37.9 145 19
# 6 MC2 884.6µs 1.96ms 393. 6.09MB 53.5 198 27
# 7 fill.NAs 89.37ms 93.1ms 10.1 4.58MB 13.5 6 8
# 8 tidyr 8.42ms 11.3ms 86.3 1.55MB 5.89 44 3
# 9 zoo 1.83ms 3.19ms 216. 7.96MB 31.9 108 16
#10 data.table 73.91µs 259.71µs 2420. 797.38KB 36.0 1210 18
#11 data.table2 54.54ms 58.71ms 16.9 3.47MB 3.75 9 2
#12 imputeTS 623.69µs 1.07ms 494. 2.69MB 30.0 247 15
#13 runner 1.36ms 1.58ms 586. 783.79KB 10.0 293 5
#14 vctrs 149.98µs 317.14µs 1725. 1.53MB 54.0 863 27
#15 ave 137.87ms 149.25ms 6.53 14.77MB 8.17 4 5
set.seed(42); y <- rnorm(n); is.na(y) <- sample(seq_along(y), n/2)
bench::mark(exprs = M) #50% NA
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl>
# 1 fillNaR 2.15ms 3.13ms 217. 7.92MB 59.7 109 30
# 2 fillNaC 949.22µs 1.09ms 728. 1.15MB 28.0 364 14
# 3 repeat.before 1.36ms 1.89ms 287. 4.77MB 49.6 185 32
# 4 RB2 1.64ms 2.44ms 347. 7.06MB 39.9 174 20
# 5 MC 1.48ms 1.92ms 443. 4.77MB 34.0 222 17
# 6 MC2 1.09ms 1.72ms 479. 5.53MB 45.9 240 23
# 7 fill.NAs 93.17ms 104.28ms 9.58 4.58MB 9.58 5 5
# 8 tidyr 7.09ms 10.07ms 96.7 1.55MB 3.95 49 2
# 9 zoo 1.62ms 2.28ms 344. 5.53MB 29.8 173 15
#10 data.table 389.69µs 484.81µs 1225. 797.38KB 14.0 613 7
#11 data.table2 27.46ms 29.32ms 33.4 3.1MB 3.93 17 2
#12 imputeTS 1.71ms 2.1ms 413. 3.44MB 25.9 207 13
#13 runner 1.62ms 1.75ms 535. 783.79KB 7.98 268 4
#14 vctrs 144.92µs 293.44µs 2045. 1.53MB 48.0 1023 24
#15 ave 66.38ms 71.61ms 14.0 10.78MB 10.5 8 6
채지의는 NA수따다음과같이결다정니됩라워에▁depending다니결정됩'.data.table::nafill또는vctrs::vec_fill_missing가장 빠릅니다.
언급URL : https://stackoverflow.com/questions/7735647/replacing-nas-with-latest-non-na-value
'programing' 카테고리의 다른 글
| 도커 내부에서 시작할 때 스프링 부팅 응용 프로그램이 부팅되지 않음 (0) | 2023.06.22 |
|---|---|
| 모든 원격 Git 분기를 로컬 분기로 추적 (0) | 2023.06.22 |
| C에서 32비트 부호 없는 정수의 특정 'n' 비트를 어떻게 추출합니까? (0) | 2023.06.22 |
| Git 브랜치를 자체 저장소로 이동하려면 어떻게 해야 합니까? (0) | 2023.06.22 |
| 왜 malloc()와 printf()가 비재입국으로 언급됩니까? (0) | 2023.06.22 |