2012-06-25 4 views
3

Попытка сделать это без цикла, но не может понять это.Найти и заменить первый NA в каждом столбце без петель

Я хочу заменить первый NA в столбце со значением по умолчанию 0.0000001.

Я делаю последнее наблюдение за переносом вперед (LOCF), но хочу присвоить ему значение по умолчанию.

Если у меня есть следующие data.frame:

> Col1  Col2  Col3  Col4 
> 1   NA   10   99 
> NA   NA   11   99 
> 1   NA   12   99 
> 1   NA   13   NA 

Я хочу, чтобы она выглядела так:

> Col1  Col2  Col3  Col4 
> 1   0.0000001 10   99 
> 0.0000001 NA   11   99 
> 1   NA   12   99 
> 1   NA   13   0.0000001 

Это код, который я haev, что работает, но очень медленно ...

#Temporary change for missing first observation 
for (u in 1:ncol(data.frame)) 
{ 
    for (v in 1:nrow(data.frame)) 
    { 
    #Temporary change the first observations in a row to 0.0000001 until it encounters a value that isn't NA 
    if(is.na(temp_equity_df_merge2[v,u])) 
    { 
     temp_equity_df_merge2[v,u]=0.0000001 
    } 
    else break 
    } 

Я хочу использовать заявку или какой-либо вариант, который будет быстрее. Я перебираю 20 столбцов и 1 миллион строк.

Спасибо за помощь.

+1

, так как вы уже LOCF, вы можете быть заинтересованы в 'библиотеке («зоопарк»); ? na.locf' – GSee

+0

Я ценю это. Это то, что я использую, но если первое наблюдение пустое, оно игнорирует его (например, оно ничего не вернет для столбца 2). Кроме того, он работает только на каждом столбце отдельно, поэтому, когда я буду использовать cbind впоследствии, они будут иметь разную длину. – Brad

ответ

1

На основе комментариев, вы можете использовать apply применить функцию к каждому столбцу. Функция заменит первый NA на 0,0000001 и вернет матрицу. Затем вы можете использовать na.locf для заполнения оставшихся NA s. Наконец, я обернул все в data.frame, так как вы просили data.frame вместо matrix

data.frame(na.locf(apply(dat, 2, function(x) { 
    firstNA <- head(which(is.na(x)), 1) #position of first NA 
    x[firstNA] <- 0.0000001 
    x 
}))) 
    Col1 Col2 Col3 Col4 
1 1e+00 1e-07 10 9.9e+01 
2 1e-07 1e-07 11 9.9e+01 
3 1e+00 1e-07 12 9.9e+01 
4 1e+00 1e-07 13 1.0e-07 
4

вы можете применить функцию к каждому столбцу:

myfun <- function(x) { 
    x[which(is.na(x))[1]] <- 0.1 

    return(x) 
} 

> data.frame(apply(dat, 2, myfun)) 
    v1 v2 v3 v4 
1 1.0 0.1 10 99.0 
2 0.1 NA 11 99.0 
3 1.0 NA 12 99.0 
4 1.0 NA 13 0.1 
> 
1

Учитывая у вас есть такой большой набор данных, я хотел бы использовать data.table и set, чтобы избежать копирования данных. Оба решения apply копируют данные не реже одного раза.

решение включает цикл, но эффективный один (делая длины (valid_replace) вещи, каждая из которых мгновенная)

library(data.table) 

DT< -as.data.table(dat) 

replacing <- lapply(DT, function(x)which(is.na(x))[1]) 

valid_replace <- Filter(Negate(is.na), replacing) 

replace_with <- 0.0001 

for(i in seq_along(valid_replace)){ 
    set(DT, i = valid_replace[i], j = names(valid_replace)[i], value = replace_with) 
} 
Смежные вопросы