清除Rdataframe中的“Inf”值
在R中,我有一个操作,当我转换dataframe时创build一些Inf
值。
我想将这些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
使用data.frame
是列的列表,然后使用do.call
重新创builddata.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
会显着降低速度。
使用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 abd 1 1 NA a 2 NA 3 b
或者你可以使用(给@mnel,这是编辑),
> is.na(dat) <- do.call(cbind,lapply(dat, is.infinite))
这是显着更快。
[<-
与mapply
比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