Запустите Java с параметром командной строки -Xmx
, который устанавливает размер maximum кучи.
Вероятно, вы хотите использовать функцию na.locf()
из пакета zoo , чтобы перенести последнее наблюдение вперед , чтобы заменить ваши значения NA.
Вот начало его примера использования на странице справки:
> example(na.locf)
na.lcf> az <- zoo(1:6)
na.lcf> bz <- zoo(c(2,NA,1,4,5,2))
na.lcf> na.locf(bz)
1 2 3 4 5 6
2 2 1 4 5 2
na.lcf> na.locf(bz, fromLast = TRUE)
1 2 3 4 5 6
2 1 1 4 5 2
na.lcf> cz <- zoo(c(NA,9,3,2,3,2))
na.lcf> na.locf(cz)
2 3 4 5 6
9 3 2 3 2
Я попробовал следующее:
nullIdx <- as.array(which(is.na(masterData$RequiredColumn)))
masterData$RequiredColumn[nullIdx] = masterData$RequiredColumn[nullIdx-1]
nullIdx получает номер idx, где когда-либо masterData $ RequiredColumn имеет значение Null / NA. В следующей строке мы заменим его соответствующим значением Idx-1, то есть последним хорошим значением перед каждым значением NULL / NA
1 NA NA
превращается в 1 1 NA
. Кроме того, я думаю, что as.array()
не требуется.
– Gregor
20 March 2017 в 00:12
Наличие ведущего NA
немного морщин, но я считаю очень читаемым (и векторизованным) способом LOCF, когда главный член not отсутствует:
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)
Бросок моей шляпы в:
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;
}
Это сработало для меня, хотя я не уверен, что он более эффективен, чем другие предложения.
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)
}
Существует множество пакетов, предлагающих функции na.locf
(NA
Last Observation Carried Forward):
xts
- xts::na.locf
zoo
- zoo::na.locf
imputeTS
- imputeTS::na.locf
spacetime
- spacetime::na.locf
А также другие пакеты, в которых это функция названа по-разному.
Продолжение вкладов Брандона Бертельсена в Rcpp. Для меня версия NumericVector не работала: она заменила только первое 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;
}')
Попробуйте эту функцию. Для него не требуется пакет 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
if (!anyNA(x)) return(x)
.
– Artem Klevtsov
27 May 2018 в 05:15
Работа с большим объемом данных, чтобы быть более эффективной, мы можем использовать пакет 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)
}
replaceNaWithLatest <- function( dfIn, nameColsNa = names(dfIn)[1] ){ dtTest <- data.table(dfIn) invisible(lapply(nameColsNa, function(nameColNa){ 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) }
– xclotet
10 January 2017 в 18:28
Вот модификация решения @ AdamO. Этот режим работает быстрее, поскольку он обходит функцию na.omit
. Это приведет к перезаписыванию значений NA
в векторе y
(кроме ведущего NA
s).
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)]
Извините, что выкапываете старый вопрос. Я не мог найти функцию, чтобы выполнить эту работу в поезде, поэтому я написал ее сам.
Я с гордостью узнал, что это немного быстрее.
Но он отлично играет с 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
Поскольку это стало моим самым Я часто напоминал, что я не использую свою собственную функцию, потому что мне часто нужен аргумент maxgap
зоопарка. Потому что у зоопарка есть некоторые странные проблемы в крайних случаях, когда я использую dplyr + даты, которые я не мог отлаживать, я вернулся к этому сегодня, чтобы улучшить свою старую функцию.
Я сравнил свою улучшенную функцию и все остальные здесь. Для базового набора функций, tidyr::fill
является самым быстрым, а также не приводит к краху. Запись Rcpp by @BrandonBertelsen еще быстрее, но она негибкая относительно типа ввода (он неправильно проверял случаи кросс-памяти из-за непонимания 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
}
Я также поставил функцию в мой пакет formr (только Github).
df
с несколькими столбцами?
– Rhubarb
6 October 2014 в 17:11
na.locf0
, которая теперь похожа по объему и производительности на вашу функцию repeat_last
. Ключ должен был использовать diff
, а не cumsum
и избегать ifelse
. Основная функция na.locf.default
все еще несколько медленнее, потому что она выполняет несколько проверок и обрабатывает несколько столбцов и т. Д.
– Achim Zeileis
2 March 2017 в 16:28
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
этот подход мог бы работать и с первичными нулями заполнения:
> 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
этот метод очень полезен для данных по шкале и где вы хотите выполнить форвардную заливку по группам (группам), что тривиально с data.table
. просто добавьте группу (ы) в предложение by
до логики cumsum
.
Это сработало для меня:
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
replace_na_with_last(c(NA,1:4,NA))
(т. е. они заполнены следующим значением). Это также поведение по умолчанию imputeTS::na.locf(x, na.remaining = "rev")
.
– Ruben
12 January 2017 в 19:32
na.locf
в зоопарке работает с обычными векторами, а также с объектами зоопарка. Его аргументna.rm
может быть полезен в некоторых приложениях. – G. Grothendieck 11 November 2016 в 14:37na.locf(cz, na.rm=FALSE)
, чтобы сохранить ведущуюNA
. – BallpointBen 17 May 2018 в 16:21