【问题标题】:Simple and efficient way to select non-NA data range in data frames在数据帧中选择非 NA 数据范围的简单有效方法
【发布时间】:2016-02-06 01:01:46
【问题描述】:

假设你有以下数据框:

dat <- data.frame(a = c(1:3, NA), b = c(letters[1:3], NA), c = NA)

> dat
   a    b  c
1  1    a NA
2  2    b NA
3  3    c NA
4 NA <NA> NA

如何以非常有效的方式选择非 NA 区域?

这是我目前使用的:

ensureNonNaRange <- function(dat) {
  idx_col <- ! sapply(dat, function(ii) all(is.na(ii)))
  idx_row <- ! sapply(1:nrow(dat), function(ii) all(is.na(unlist(dat[ii, ]))))
  dat[idx_row, idx_col]
}

> ensureNonNaRange(dat)
  a b
1 1 a
2 2 b
3 3 c

直到今天我才被指出了一个非常有用的函数 type.convert,这是我以前不知道的,我认为在 base R 中可能还存在一些类似于此任务的“现成”的东西。

更新

基于我得到的答案/cmets的一些比较:

ensureNonNaRange2 <- function(dat) {
  dat[rowSums(!is.na(dat)) != 0, colSums(!is.na(dat)) != 0]
}

microbenchmark::microbenchmark(
  a = ensureNonNaRange(dat),
  b = ensureNonNaRange2(dat)
)

Unit: microseconds
 expr     min       lq     mean   median       uq     max neval
    a 296.178 310.1070 346.2259 329.0210 349.9875 680.035   100
    b 112.313 120.0845 134.1716 125.6555 133.7200 338.112   100

【问题讨论】:

  • 不是现成的,而是在一行中:dat[rowSums(!is.na(dat)) != 0, colSums(!is.na(dat)) != 0]
  • @alistaire:整洁!几乎是我的两倍,而且非常紧凑。非常感谢!想提供这个作为答案吗?
  • 如果dat[2, 3] 不是 NA?

标签: r indexing dataframe na


【解决方案1】:

虽然可能还有一些内置函数可以做到这一点,但您可以通过子集来做到这一点。

is.na 传递一个完整的data.frame 时,它会生成一个布尔掩码,因此如果您将!is.na(dat) 的行和列相加(即添加TRUE 的值not em> NA),对于只有 NAs 的行和列,你得到的总和为零。

因此,如果我们按行和列的总和为!= 0 时进行子集化,则剩下的行和列的值不是NA

> dat[rowSums(!is.na(dat)) != 0, colSums(!is.na(dat)) != 0]
  a b
1 1 a
2 2 b
3 3 c

如果行或列中的某些但不是所有值都是 NA,则此方法会保留该行/列:

> dat[2,2] <- NA
> dat[rowSums(!is.na(dat)) != 0, colSums(!is.na(dat)) != 0]
  a    b
1 1    a
2 2 <NA>
3 3    c

(如果您想用 any NAs 放弃行/列,请调整感叹号,或使用 complete.cases。)

此外,它应该非常快,因为rowSumscolSums 进行了高度优化,因此它仍然可以在巨大的数据结构上快速运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 2017-09-08
    • 1970-01-01
    • 2019-03-30
    相关资源
    最近更新 更多