ric*_*rdo 95 r dataframe data.table
在R中,我有一个操作,Inf当我转换数据帧时会创建一些值.
我想将这些Inf值转换为NA值.我的代码对于大数据来说速度慢,有没有更快的方法呢?
说我有以下数据帧:
dat <- data.frame(a=c(1, Inf), b=c(Inf, 3), d=c("a","b"))
Run Code Online (Sandbox Code Playgroud)
以下适用于单个案例:
dat[,1][is.infinite(dat[,1])] = NA
Run Code Online (Sandbox Code Playgroud)
所以我用以下循环推广它
cf_DFinf2NA <- function(x)
{
for (i in 1:ncol(x)){
x[,i][is.infinite(x[,i])] = NA
}
return(x)
}
Run Code Online (Sandbox Code Playgroud)
但我不认为这是真正使用R的力量.
mne*_*nel 111
使用a data.frame是列表列表的事实,然后用于do.call重新创建a data.frame.
do.call(data.frame,lapply(DT, function(x) replace(x, is.infinite(x),NA)))
Run Code Online (Sandbox Code Playgroud)
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)))
Run Code Online (Sandbox Code Playgroud)
或者使用列号(如果有很多列,可能会更快):
for (j in 1:ncol(DT)) set(DT, which(is.infinite(DT[[j]])), j, NA)
Run Code Online (Sandbox Code Playgroud)
# 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
Run Code Online (Sandbox Code Playgroud)
data.table是最快的.使用sapply会显着降低速度.
42-*_*42- 57
使用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
Run Code Online (Sandbox Code Playgroud)
或者你可以使用(归功于@mnel,其编辑是这样的),
> is.na(dat) <- do.call(cbind,lapply(dat, is.infinite))
Run Code Online (Sandbox Code Playgroud)
这明显更快.
Ric*_*ven 18
[<-与... mapply相比有点快sapply.
> dat[mapply(is.infinite, dat)] <- NA
Run Code Online (Sandbox Code Playgroud)
根据mnel的数据,时间是
> system.time(dat[mapply(is.infinite, dat)] <- NA)
# user system elapsed
# 15.281 0.000 13.750
Run Code Online (Sandbox Code Playgroud)
这是使用na_if()函数的dplyr / tidyverse解决方案:
dat %>% mutate_if(is.numeric, list(~na_if(., Inf)))
Run Code Online (Sandbox Code Playgroud)
请注意,这仅用NA替代正无穷大。如果还需要替换负无穷大值,则需要重复。
dat %>% mutate_if(is.numeric, list(~na_if(., Inf))) %>%
mutate_if(is.numeric, list(~na_if(., -Inf)))
Run Code Online (Sandbox Code Playgroud)
这个问题在 hablar 包中有一个非常简单的解决方案:
library(hablar)
dat %>% rationalize()
Run Code Online (Sandbox Code Playgroud)
其中返回的数据帧与所有 Inf 都转换为 NA。
与上述一些解决方案相比的时间。代码:库(hablar) 库(data.table)
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))
DT <- data.table(dat)
system.time(dat[mapply(is.infinite, dat)] <- NA)
system.time(dat[dat==Inf] <- NA)
system.time(invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA))))
system.time(rationalize(dat))
Run Code Online (Sandbox Code Playgroud)
结果:
> system.time(dat[mapply(is.infinite, dat)] <- NA)
user system elapsed
0.125 0.039 0.164
> system.time(dat[dat==Inf] <- NA)
user system elapsed
0.095 0.010 0.108
> system.time(invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA))))
user system elapsed
0.065 0.002 0.067
> system.time(rationalize(dat))
user system elapsed
0.058 0.014 0.072
>
Run Code Online (Sandbox Code Playgroud)
似乎 data.table 比 hablar 快。但有更长的语法。
| 归档时间: |
|
| 查看次数: |
92292 次 |
| 最近记录: |