114

InfR では、データフレームを変換するときに いくつかの値を作成する操作があります。

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 の力を使っているとは思いません。

4

11 に答える 11

128

オプション1

data.frameaが列のリストであることを利用して、 を使用do.callして a を再作成し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すると、処理が著しく遅くなります。

于 2012-08-30T01:04:43.167 に答える
61

使用sapplyしてis.na<-

> dat <- data.frame(a=c(1, Inf), b=c(Inf, 3), d=c("a","b"))
> is.na(dat) <- sapply(dat, is.infinite)
> dat
   a  b d
1  1 NA a
2 NA  3 b

または、使用できます (これを編集した @mnel に謝意を表します)、

> is.na(dat) <- do.call(cbind,lapply(dat, is.infinite))

これは大幅に高速です。

于 2012-08-30T01:12:49.920 に答える
19

[<-withmapplyは よりも少し高速ですsapply

> dat[mapply(is.infinite, dat)] <- NA

mnelのデータでは、タイミングは

> system.time(dat[mapply(is.infinite, dat)] <- NA)
#   user  system elapsed 
# 15.281   0.000  13.750 
于 2014-09-18T07:36:31.377 に答える