【问题标题】:find last row where at least one column is not NA找到至少一列不是 NA 的最后一行
【发布时间】:2020-06-26 10:22:05
【问题描述】:

我有一个对象,在一定数量的行之后,每列中都有所有 NA。在此之前,某些列还具有 NA。我想获取至少一列中有数据的最后一行的行索引。以下是一些可以使用的示例数据:

编辑:为了稳健,我在第二行添加了 NA,跟在 @G 之后。格洛腾迪克厘米。在这种情况下,输出仍应为 5。

df <- data.frame(a = 1:5, b = 6:10, c = c(1:3,rep(NA, 2)))
df <- rbind(df, rep(NA, ncol(df)), rep(NA, ncol(df)))
df[2,] <- NA

df
   a  b  c
1  1  6  1
2 NA NA NA
3  3  8  3
4  4  9 NA
5  5 10 NA
6 NA NA NA
7 NA NA NA

【问题讨论】:

  • 也可以考虑max(sapply(df, function(x) max(which(!is.na(x)))))

标签: r dataframe dplyr data.table data-manipulation


【解决方案1】:

另一种选择:

nrow(df[!apply(df, 1, function(x) all(is.na(x))), ])

# [1] 5

请注意,这仅适用于具有所有缺失值的行位于数据框的最末尾的情况,例如正如@G.Grothendieck 所提到的,它会因df[2, ] &lt;- NA 而失败。

解决这些边缘情况的另一种选择是:

sum(cumsum(rowSums(df[rev(rownames(df)),], na.rm = TRUE)) != 0)

# [1] 5

【讨论】:

  • 如果 df[2, ] 给出 4 而不是 5
  • 谢谢@G.Grothendieck,确实 - 会提到这一点。
【解决方案2】:

[1]我们可以使用rowSums创建一个逻辑向量并用which包裹返回索引

tail(which(rowSums(!is.na(df)) > 0), 1)
#[1] 5

[2] 或者另一个选项是lengths。删除每列中的NA

max(lengths(lapply(df, na.omit)))
#[1] 5

此选项在某些边缘情况下可能会失败,如 cmets 中提到的@G Grothendieck,即当特定行在最后一组 NA 行之前全部为 NA 时


[3] 或者另一个选项是 whicharr.ind 在逻辑矩阵上的选项

max(which(!is.na(df), arr.ind = TRUE)[,1])
#[1] 5

[4]rowis.na

max(row(df) * NA^is.na(df), na.rm = TRUE)
#[1] 5

注意:所有方法都使用 base R 并且不需要额外的包

【讨论】:

  • (2) 为 df[2, ] 给出 4 而不是 5
  • @G.Grothendieck 是的,谢谢,这是我没有考虑过的极端情况
【解决方案3】:

1) na.trim 这会从底部删除所有为 NA 的行,然后返回剩余的行数:

library(zoo)
nrow(na.trim(df, "right", is.na = "all"))
## [1] 5

2) Base R 我们可以将每个非 NA 替换为其行号,然后取这些数字中的最大值:

max(ifelse(is.na(df), NA, row(df)), na.rm = TRUE)
## [1] 5

2a)如果所有条目都是数字,如问题所示,则可以缩短为:

max(row(df) + 0 * df, na.rm = TRUE)
## [1] 5

【讨论】:

  • 肯定会经常遇到一行 NA,这是基本情况,而不是边缘情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
  • 2021-05-02
相关资源
最近更新 更多