Gna*_*ark 127 r apply dataframe
我有一个数据帧麻烦,不能真正解决这个问题我自己:
该数据帧具有任意的性质列和每一行代表一个数据集.
问题是:
如何摆脱所有行的值为NA的列?
teu*_*cer 141
试试这个:
df <- df[,colSums(is.na(df))<nrow(df)]
Run Code Online (Sandbox Code Playgroud)
mne*_*nel 88
到目前为止提供的两种方法都失败了,因为它们创建了大型数据集(在其他内存问题中)is.na(df),这将是一个与其大小相同的对象df.
以下两种方法具有更高的内存和时间效率
使用的方法 Filter
Filter(function(x)!all(is.na(x)), df)
Run Code Online (Sandbox Code Playgroud)
和使用data.table的方法(一般时间和内存效率)
library(data.table)
DT <- as.data.table(df)
DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]
Run Code Online (Sandbox Code Playgroud)
big_data <- replicate(10, data.frame(rep(NA, 1e6), sample(c(1:8,NA),1e6,T), sample(250,1e6,T)),simplify=F)
bd <- do.call(data.frame,big_data)
names(bd) <- paste0('X',seq_len(30))
DT <- as.data.table(bd)
system.time({df1 <- bd[,colSums(is.na(bd) < nrow(bd))]})
# error -- can't allocate vector of size ...
system.time({df2 <- bd[, !apply(is.na(bd), 2, all)]})
# error -- can't allocate vector of size ...
system.time({df3 <- Filter(function(x)!all(is.na(x)), bd)})
## user system elapsed
## 0.26 0.03 0.29
system.time({DT1 <- DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]})
## user system elapsed
## 0.14 0.03 0.18
Run Code Online (Sandbox Code Playgroud)
zac*_*ack 37
dplyr现在有一个select_if动词可能对此有帮助:
library(dplyr)
temp <- data.frame(x = 1:5, y = c(1,2,NA,4, 5), z = rep(NA, 5))
not_all_na <- function(x) any(!is.na(x))
not_any_na <- function(x) all(!is.na(x))
> temp
x y z
1 1 1 NA
2 2 2 NA
3 3 NA NA
4 4 4 NA
5 5 5 NA
> temp %>% select_if(not_all_na)
x y
1 1 1
2 2 2
3 3 NA
4 4 4
5 5 5
> temp %>% select_if(not_any_na)
x
1 1
2 2
3 3
4 4
5 5
Run Code Online (Sandbox Code Playgroud)
Sve*_*enB 20
套餐的另一个选项purrr:
library(dplyr)
df <- data.frame(a = NA,
b = seq(1:5),
c = c(rep(1, 4), NA))
df %>% purrr::discard(~all(is.na(.)))
df %>% purrr::keep(~!all(is.na(.)))
Run Code Online (Sandbox Code Playgroud)
mro*_*opa 15
另一种方法是使用该apply()功能.
如果你有data.frame
df <- data.frame (var1 = c(1:7,NA),
var2 = c(1,2,1,3,4,NA,NA,9),
var3 = c(NA)
)
Run Code Online (Sandbox Code Playgroud)
那么你可以apply()用来查看哪些列满足你的条件,所以你可以简单地做一个与Musa的答案相同的子集,只有一个apply方法.
> !apply (is.na(df), 2, all)
var1 var2 var3
TRUE TRUE FALSE
> df[, !apply(is.na(df), 2, all)]
var1 var2
1 1 1
2 2 2
3 3 1
4 4 3
5 5 4
6 6 NA
7 7 NA
8 NA 9
Run Code Online (Sandbox Code Playgroud)
这是一个老问题,但我认为我们可以用更简单的 data.table 解决方案更新 @mnel 的好答案:
DT[, .SD, .SDcols = \(x) !all(is.na(x))]
Run Code Online (Sandbox Code Playgroud)
(我正在使用 R>=4.1 中可用的新\(x)lambda 函数语法,但实际上关键是将逻辑子集传递给.SDcols.
速度相当。
DT[, .SD, .SDcols = \(x) !all(is.na(x))]
Run Code Online (Sandbox Code Playgroud)
游戏晚了,但您也可以使用该janitor程序包。此函数将删除全部为NA的列,并且可以更改为也删除全部为NA的行。
df <- janitor::remove_empty(df, which = "cols")