Есть ли R-функция, которая делает противоположность dplyr :: coalesce ()? - PullRequest
1 голос
/ 10 ноября 2019

Вызов dplyr::coalesce возвращает первые не пропущенные значения:

> vec1 <- c(11, 12, NA, NA, NA)
> vec2 <- c(21, 22, NA, NA, 25)
> vec3 <- c(NA, 32, NA, 34, 35)
> coalesce(vec1, vec2, vec3)
[1] 11 12 NA 34 25

, что аналогично вызову vec1 | vec2 | vec3 (возврат значений вместо логических).

Есть ли функцияаналогично vec1 & vec2 & vec3, возвращая последнее значение, если ничего не пропущено? Это стоит тонны, но я не могу найти краткий / простой способ сделать это.

> vec1 <- c(11, 12, NA, NA, NA)
> vec2 <- c(21, 22, NA, NA, 25)
> vec3 <- c(NA, 32, NA, 34, 35)
> ideal_fn(vec1, vec2, vec3)
[1] NA 32 NA NA NA

Для чисел и логики я могу сделать это легко / кратко с vec3[vec1 & vec2 & vec3] или ifelse(vec1 & vec2, vec3). Но они не работают с символьными векторами.

Есть ли что-то лучше, чем ifelse(!is.na(vec1) & !is.na(vec2) & !is.na(vec3), vec3, NA)? Мне кажется, что это очень окольный способ решения очень простой проблемы.

Ответы [ 2 ]

1 голос
/ 10 ноября 2019

Мы можем использовать pmax без na.rm

pmax(vec1, vec2, vec3)
#[1] NA 32 NA NA NA

Или другой вариант - max.col с ties.method = 'last'. Создайте матрицу или data.frame с векторами, затем примените max.col, чтобы получить индекс столбца со значением max для каждой строки, cbind с последовательностью строк и извлечь соответствующие значения. Если строка имеет только NA s, индекс столбца будет NA и, таким образом, получит NA

m1 <- cbind(vec1, vec2, vec3)
m1[cbind(seq_len(nrow(m1)), max.col(m1, 'last'))]
#[1] NA 32 NA NA NA

Если это основано на позиции, а не на максимальных значениях

m2 <- col(m1) * NA^is.na(m1)
m1[cbind(seq_len(nrow(m1)), max.col(m2, 'last'))]
#[1] NA 32 NA NA NA

Или, если имеется больше векторов, другой вариант - создать логический вектор с Reduce

i1 <- Reduce(`|`, lapply(mget(paste0("vec", 1:3)), is.na))
replace(vec3, i1, NA)
#[1] NA 32 NA NA NA

Или с использованием rowSums

vec3 * NA^!!rowSums(is.na(cbind(vec1, vec2, vec3)))
#[1] NA 32 NA NA NA

ПРИМЕЧАНИЕ: обе функции base R

0 голосов
/ 10 ноября 2019

Я бездельничал и нашел более чистый способ, используя tidyverse:

and_values <- . %>%
  reduce(~ ifelse(is.na(.x), NA, .y))

> and_values(list(vec1, vec2, vec3))
[1] NA 32 NA NA NA
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...