найти последнюю строку, где хотя бы один столбец не является NA - PullRequest
0 голосов
/ 14 марта 2020

У меня есть объект, в котором есть все 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

Ответы [ 3 ]

4 голосов
/ 14 марта 2020

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) Если все записи являются номерами c, как в вопросе, то это может быть сокращено до:

max(row(df) + 0 * df, na.rm = TRUE)
## [1] 5
2 голосов
/ 14 марта 2020

[1] Мы можем использовать rowSums, чтобы создать логический вектор, и обернуть с помощью which, чтобы вернуть индекс

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

[2 ] Или другой вариант - lengths. после удаления NA в каждом столбце

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

Эта опция может не работать в некоторых крайних случаях, как упомянуто в комментариях @G Grothendieck, т. е. когда вся конкретная строка представляет собой NA перед последним набором строк NA


[3] Или другой вариант which с параметром arr.ind в логической матрице

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

[4] или с row и is.na

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

ПРИМЕЧАНИЕ. Все подходы используют base R и не требуют дополнительных пакетов

0 голосов
/ 14 марта 2020

Другой вариант:

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

# [1] 5

Обратите внимание, что это работает только в том случае, если строки со всеми пропущенными значениями находятся в самом конце вашего фрейма данных, например, произойдет сбой с df[2, ] <- NA, как упомянуто @G .Grothendieck.

Еще один вариант решения этих крайних случаев:

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

# [1] 5
...