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

Posted

技术标签:

【中文标题】是否有与 dplyr::coalesce() 相反的 R 函数?【英文标题】:Is there an R function that does the opposite of dplyr::coalesce()? 【发布时间】:2019-11-10 18:48:38 【问题描述】:

调用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 &amp; vec2 &amp; 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 &amp; vec2 &amp; vec3]ifelse(vec1 &amp; vec2, vec3) 轻松/简洁地做到这一点。但它们不适用于字符向量。

还有比ifelse(!is.na(vec1) &amp; !is.na(vec2) &amp; !is.na(vec3), vec3, NA)更好的东西吗?只是让我觉得解决一个非常简单的问题的一种非常迂回的方式。

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

它是基于位置的,所以pmax 不幸的是无法工作。而且我认为我仍然会选择 ifelse(!is.na(vec1) &amp; !is.na(vec2) &amp; !is.na(vec3), vec3, NA) 而不是选项 2,因为它更容易阅读 @Nick 如果是基于位置,我也编辑了那个案例。请阅读整个解决方案,而不是第一个。如果向量超过 10 个,则可以将 &amp; 更改为 i1 &lt;- Reduce('&amp;', !lapply(mget(paste0("vec", 1:3)), is.na)); ifelse(i1, vec3, NA)【参考方案2】:

我搞砸了,只是找到了一种使用 tidyverse 的更清洁的方法:

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

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

【讨论】:

以上是关于是否有与 dplyr::coalesce() 相反的 R 函数?的主要内容,如果未能解决你的问题,请参考以下文章

numpy.pad() 函数是不是有相反/反向的功能?

是否有与 Haskell 'let' 等效的 Python

是否有与 Mysql 的“多语句查询”等效的 java

是否有与 Amazon S3 等效的开源软件? [关闭]

是否有与 RecyclerView 等效的 addHeaderView?

是否有与 Ruby 符号等效的 Python?