后台
几种SQL语言(我主要使用PostgreSQL)都有一个名为coalesce的函数,它返回每行的第一个非空列元素。当表中有很多NULL
元素时,使用这种方法非常有效。
我在R中的很多场景中遇到过这种情况,当处理不那么结构化的数据时,其中有很多NA。
我自己做了一个简单的实现,但它慢得可笑。
coalesce <- function(...) {
apply(cbind(...), 1, function(x) {
x[which(!is.na(x))[1]]
})
}
示例
a <- c(1, 2, NA, 4, NA)
b <- c(NA, NA, NA, 5, 6)
c <- c(7, 8, NA, 9, 10)
coalesce(a,b,c)
# [1] 1 2 NA 4 6
提问
在R中有没有有效的方法来实现coalesce
?
9条答案
按热度按时间t5zmwmid1#
在我的机器上,使用
Reduce
可以获得5倍的性能提升:jk9hmnmh2#
看起来coalesce1仍然可用
这仍然更快(但或多或少是手工重写的
Reduce
,因此不太通用)或对于更大的数据比较
这表明
which()
有时是有效的,即使它意味着第二次通过索引。eimct9ow3#
从
data.table >= 1.12.3
可以使用fcoalesce
。fcoalesce
也可以采用“单个普通列表、data.table或data.frame”。因此,如果上面的向量是data.frame
(或data.table
)中的列,我们可以简单地提供数据集的名称:有关更多信息,包括基准测试,请参阅NEWS项目#18开发版本1.12.3。
bvjveswy4#
使用 dplyr 包:
Benchamark,不如公认的解决方案快:
但在更大的数据集上,它是可比的:
mjqavswn5#
我在my misc package中有一个名为
coalesce.na
的现成实现。它看起来很有竞争力,但不是最快的。它也适用于不同长度的向量,并对长度为1的向量进行特殊处理:代码如下:
当然,正如Kevin所指出的,Rcpp解决方案可能会快几个数量级。
w8f9ii696#
一个非常简单的解决方案是使用
base
包中的ifelse
函数:虽然它看起来比上面的
coalesce2
慢:您可以使用
Reduce
使其适用于任意数量的向量:e5nqia277#
以下是我的解决方案:
coalesce <- function(x){ y <- head( x[is.na(x) == F] , 1) return(y) }
它返回第一个不是NA的值,它适用于data.table
,例如,如果你想在几个列上使用合并,这些列名是字符串的向量:column_names <- c("col1", "col2", "col3")
如何用途:
ranking[, coalesce_column := coalesce( mget(column_names) ), by = 1:nrow(ranking)]
e7arh2l68#
BASE中的一个优雅的解决方案是定义:
coalesce <- function(...) na.omit(c(...))[1]
对于vector:
输出是所需的:
在我的机器上,这击败了使用
Reduce
的公认答案。ao218c7q9#
另一个apply方法,使用
mapply
。如果存在多个非NA值,则选择第一个非NA值。最后一个非缺失元素可以使用
tail
选择。也许可以使用基本的
.mapply
函数(看起来有点不同)来提高速度。.mapply
在重要方面不同于它的非点表兄弟。Map
),因此必须 Package 在一些函数中,如unlist
或c
以返回向量。mapply
,moreArgs参数没有默认值,因此必须显式地提供NULL。