Inf
R では、データフレームを変換するときにいくつかの値を作成する操作があります。
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
オプション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
速度が著しく低下します。