尝试在没有For Loop的情况下执行此操作,但无法弄明白。
我想用默认值0.0000001替换列中的第一个NA。
我正在进行最后观察前进(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
这是我可以使用的代码,但速度非常慢......
#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
}
我想使用apply或一些更快的变体。我正在循环超过20列和100万行。
提前感谢您的帮助。
答案 0 :(得分: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 :(得分:1)
根据评论,您可以使用apply
将函数应用于每列。该函数将用0.0000001替换第一个NA
并返回一个矩阵。然后,您可以使用na.locf
填写剩余的NA
。最后,由于您要求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
答案 2 :(得分:1)
鉴于您拥有如此庞大的数据集,我会使用data.table
和set
来避免复制数据。 apply
个解决方案都至少复制一次数据。
解决方案涉及一个for循环,但是一个有效的循环(做长度(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)
}