是否有R函数与dplyr :: coalesce()相反?

时间:2019-11-10 18:48:38

标签: r dplyr

调用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)好吗?令我震惊的是解决一个非常简单的问题的一种problem回的方式。

2 个答案:

答案 0 :(得分:1)

我们可以在没有pmax的情况下使用na.rm

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

或者另一个选项是max.colties.method = 'last'。使用向量创建矩阵或data.frame,然后应用max.col以获取每一行上max值的列索引,cbind包含行序列并提取相应的值。如果一行仅包含NA,则列索引将为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函数

答案 1 :(得分:0)

我搞乱了,只是发现了使用tidyverse的一种更清洁的方法:

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

> and_values(list(vec1, vec2, vec3))
[1] NA 32 NA NA NA