使用data.table返回出现在每列中的特定值的计数向量

fre*_*rip 1 r dplyr data.table

我有一个非常大的data.table,并且一直试图返回每列中特定默认值计数的列表或向量(它们每列不同).它是这样组织的:

set.seed(1); 
DT = as.data.table(matrix(sample(1:100, 100*100, TRUE), 100, 100))
#DT output below
param1  param2  param3  ... param100 #column names
1       1       1       ... 1        #first row = default values
.                                    #elems in remaining rows are random
.                                    # a param can be set to non default
1       666     1       ... 143      # or default values within a column
.
.
10000   1       1       ... 420
Run Code Online (Sandbox Code Playgroud)

我很想知道data.table的做法是什么?我一直在筛选过去的文档,并试图避免使用内存和计算密集的循环和方法(我试图使用过滤器,lapply和分组,没有运气).

我理想地寻找的一个类似的例子是计算每列存在的非NA值的数量:

count <- colSums(!is.na(DT))
#which outputs the following:
print(count)
param1  param2  param3  ... param177
1       292     0           7
Run Code Online (Sandbox Code Playgroud)

colSums(!is.na(DT))除了特定于每列的给定默认值之外,有没有办法与方法类似?因此,不是计算给定列的非NA值,而是计算出我的DT的每一列中出现的非默认值,其中每列的每个默认值都位于第一行.

Fra*_*ank 6

好吧,我认为这就是:

set.seed(1)
DT = as.data.table(matrix(sample(1:1e5, 1e8, TRUE), ncol = 10))

# vector scan
sapply(DT, function(x) sum(x == x[1L]))
#  V1  V2  V3  V4  V5  V6  V7  V8  V9 V10 
# 124 100 111 101 113 101  94 108  79 112 

# binary search
sapply(names(DT), function(x){
    q = substitute(x == x[1L], list(x=as.symbol(x)))
    DT[eval(q), .N]
})
#  V1  V2  V3  V4  V5  V6  V7  V8  V9 V10 
# 124 100 111 101 113 101  94 108  79 112 
Run Code Online (Sandbox Code Playgroud)

基准:

  • 矢量扫描需要0.22秒
  • 二进制搜索最初需要1.8秒
  • 每次在此之后立即进行二进制搜索

该加速是由于指数在data.table,更具体的自动索引.查看?indices和阅读小插曲(这一个出现在第四个).指数也将加快数据的其他操作.要从头开始创建它们for (nm in names(DT)) setindexv(DT, nm),但是当然这将花费大约1.8秒.

注意:如果您的数据是浮点数,无论您如何处理,都会遇到麻烦.浮点数不像平等测试那样好玩x==x[1L].