天道酬勤,学无止境

R: table function suprisingly slow

> class(v)
"numeric"
> length(v)
80373285   # 80 million

The entries of v are integers uniformly distributed between 0 and 100.

> ptm  <-  proc.time()
> tv   <-  table(v)
> show(proc.time() - ptm)
   user  system elapsed 
 96.902   0.807  97.761 

Why is the table function so slow on this vector?

Is there a faster function for this simple operation?

By comparison, the bigtable function from bigtabulate is fast:

> library(bigtabulate)
> ptm  <-  proc.time() ;  bt <- bigtable(x = matrix(v,ncol=1), ccols=1) ; show(proc.time() - ptm)
   user  system elapsed 
  4.163   0.120   4.286 

While bigtabulate is a good solution, it seems unwieldy to resort to a special package just for this simple function. Technically, there is overhead because I am contorting a vector into a matrix to make it work with bigtable. Shouldn't there be simpler, faster solution in base R?

For whatever its worth, the base R function cumsum is extremely fast even for this long vector:

> ptm  <-  proc.time() ; cs   <-  cumsum(v) ; show(proc.time() - ptm)
   user  system elapsed 
  0.097   0.117   0.214 
标签

评论

Because it calls factor first. Try tabulate if all your entries are integers. But you need to plus 1, so that the vector values start from 1 not 0.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 为什么要使用as.factor()而不是仅使用factor()(Why use as.factor() instead of just factor())
    问题 我最近看到Matt Dowle用as.factor()编写了一些代码,特别是 for (col in names_factors) set(dt, j=col, value=as.factor(dt[[col]])) 在对此答案的评论中。 我使用了此代码段,但是我需要显式设置因子水平以确保水平按所需顺序显示,因此我必须进行更改 as.factor(dt[[col]]) 至 factor(dt[[col]], levels = my_levels) 这让我开始思考:使用as.factor()与仅使用factor()什么好处(如果有factor() ? 回答1 as.factor是factor的包装器,但是如果输入向量已经是factor,它可以快速返回: function (x) { if (is.factor(x)) x else if (!is.object(x) && is.integer(x)) { levels <- sort(unique.default(x)) f <- match(x, levels) levels(f) <- as.character(levels) if (!is.null(nx <- names(x))) names(f) <- nx class(f) <- "factor" f } else factor(x) } 弗兰克的评论
  • PartitionKey / RowKey列表上的Azure表存储查询非常慢(Very Slow on Azure Table Storage Query on PartitionKey/RowKey List)
    问题 GET /Product()?$filter=((PartitionKey%20eq%20'lIkfA81JpTmv')%20and%20(RowKey%20eq%20'')) %20or%20((PartitionKey%20eq%20'lIGcEmrr7hWz')%20and%20(RowKey%20eq%20'')) %20or%20((PartitionKey%20eq%20'lIAoy6PqeMVn')%20and%20(RowKey%20eq%20'')) %20or%20((PartitionKey%20eq%20'lIjETAtuhYGM')%20and%20(RowKey%20eq%20'')) %20or%20((PartitionKey%20eq%20'lIHa0znP5qAk')%20and%20(RowKey%20eq%20'')) %20or%20((PartitionKey%20eq%20'lIOCaSXg9YE7')%20and%20(RowKey%20eq%20'')) %20or%20((PartitionKey%20eq%20'lInRozGrMa7T')%20and%20(RowKey%20eq%20'')) %20or%20((PartitionKey%20eq%20'lILEwwPPcBfe')%20and%20(RowKey
  • Slow bitwise operations
    I am working on a Python library that performs a lot of bitwise operations on long bit strings, and I want to find a bit string type that will maximize its speed. I have tried the built-in Python int type, numpy, bitstring, and bitarray, and suprisingly, the Python ints seem to win hands down when it comes to bitwise operations. Everything I have googled says numpy should be much faster for vectorized operations like this. Am I using numpy wrong somehow? Is there another Python library I can use that actually improves on Python's built-in int type? from timeit import timeit import random size
  • 慢按位运算(Slow bitwise operations)
    问题 我正在研究一个Python库,该库对长位字符串执行很多按位运算,并且我想找到一种位字符串类型,以最大程度地提高其速度。 我已经尝试了内置的Python int类型,numpy,bitstring和bitarray,而且令人惊讶的是,在按位操作方面,Python int似乎可以胜任。 我搜索过的所有内容都说numpy对于这样的矢量化操作应该要快得多。 我是否以某种方式使用numpy错误? 我是否可以使用另一个Python库,该库实际上对Python的内置int类型有所改进? from timeit import timeit import random size = 10000 def int_to_bits(i): result = [] for _ in range(size): result.append(i % 2) i >>= 1 return result x = random.randrange(2**size) y = random.randrange(2**size) print(x.bit_length(), y.bit_length()) x_bits = int_to_bits(x) y_bits = int_to_bits(y) t = timeit( stmt='a & b', setup='a = %d; b = %d' % (x, y) )
  • 如何获得比numpy.dot更快的代码进行矩阵乘法?(How to get faster code than numpy.dot for matrix multiplication?)
    问题 在这里,使用hdf5进行矩阵乘法时,我使用hdf5(pytables)进行大型矩阵乘法,但令我惊讶的是,使用hdf5比使用普通numpy.dot更快,并且将矩阵存储在RAM中,这种行为的原因是什么? 也许在python中有一些更快的矩阵乘法功能,因为我仍然使用numpy.dot进行小块矩阵乘法。 这是一些代码: 假设矩阵可以容纳在RAM中:在10 * 1000 x 1000的矩阵上进行测试。 使用默认的numpy(我认为没有BLAS lib)。 普通的numpy数组在RAM中:时间9.48 如果RAM中的A,B,磁盘上的C:时间1.48 如果磁盘上有A,B,C:时间372.25 如果我将numpy与MKL一起使用,则结果为:0.15、0.45、43.5。 结果看起来合理,但我仍然不明白为什么在第一种情况下块乘法更快(当我们将A,B存储在RAM中时)。 n_row=1000 n_col=1000 n_batch=10 def test_plain_numpy(): A=np.random.rand(n_row,n_col)# float by default? B=np.random.rand(n_col,n_row) t0= time.time() res= np.dot(A,B) print (time.time()-t0) #A,B in RAM, C on disk
  • Loop with function call faster than an empty loop
    I linked some assembly with some c to test the cost of a function call, with the following assembly and c source (using fasm and gcc respectively) assembly: format ELF public no_call as "_no_call" public normal_call as "_normal_call" section '.text' executable iter equ 100000000 no_call: mov ecx, iter @@: push ecx pop ecx dec ecx cmp ecx, 0 jne @b ret normal_function: ret normal_call: mov ecx, iter @@: push ecx call normal_function pop ecx dec ecx cmp ecx, 0 jne @b ret c source: #include <stdio.h> #include <time.h> extern int no_call(); extern int normal_call(); int main() { clock_t ct1, ct2
  • 在VBA(Excel)中循环浏览行的最有效/最快捷的方法是什么?(What is the most efficient/quickest way to loop through rows in VBA (excel)?)
    问题 我知道Excel中的VBA并不是最快的方法-但是我需要最有效(即最快)的方法来遍历大量行样本。 目前我有: For Each c In Range("$A$2:$A$" & Cells(Rows.count, "A").End(xlUp).row ' do stuff Next c “要做的事情”包括在此插入一行(因此,我需要保持范围的动态查找。) 有什么主意(超过10,000行)? 编辑我已经在使用 Application.ScreenUpdating = False Application.Calculation = xlManual 回答1 如果只循环A列中的1万行,则将其转储到变量数组中,然后循环遍历。 然后,您可以将元素添加到新数组中(同时在需要时添加行),并使用Transpose()一步将数组放到您的范围内,也可以使用迭代器变量来跟踪您所在的行并添加这样行。 Dim i As Long Dim varray As Variant varray = Range("A2:A" & Cells(Rows.Count, "A").End(xlUp).Row).Value For i = 1 To UBound(varray, 1) ' do stuff to varray(i, 1) Next 这是在评估每个单元格后如何添加行的示例。 本示例仅在A列中每个包含单词“
  • 如何在SQL中表示数据树?(How to represent a data tree in SQL?)
    问题 我正在写一个由Tree和TreeNode组合而成的数据树结构。 树将包含根和数据上的顶级操作。 我正在使用UI库以Windows窗体呈现树,可以在其中将树绑定到TreeView。 我将需要将此树和节点保存在数据库中。 保存树并获得以下功能的最佳方法是什么: 直观的实现。 易于装订。 从树到数据库结构的移动很容易(如果有的话) 我有两个想法。 第一种是将数据序列化成表格中的一个衬板。 第二种是保存在表中,但是当移到数据实体时,我将在已更改的节点上松开表上的行状态。 有任何想法吗? 回答1 我已将此幻灯片共享标记为SQL-Antipatterns,其中讨论了几种替代方法:http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back?src=embed 那里的建议是使用封闭表(在幻灯片中对此进行了说明)。 这是摘要(幻灯片77): | Query Child | Query Subtree | Modify Tree | Ref. Integrity Adjacency List | Easy | Hard | Easy | Yes Path Enumeration | Easy | Easy | Hard | No Nested Sets | Hard | Easy | Hard | No Closure
  • 旋转:设置哪一位?(Bit twiddling: which bit is set?)
    问题 我有一个设置为1位的64位无符号整数。 我想为每个可能的64个值分配一个值(在这种情况下,为奇质数,因此0x1对应于3,0x2对应于5,…,0x8000000000000000对应于313)。 似乎最好的方法似乎是将1→0、2→1、4→2、8→3,…,2 63 →63转换为数组中的值。 但是,即使是这样,我也不确定以二进制指数获取最快的方法是什么。 而且可能还有更有效的方法。 此操作将使用10 14到10 16次,因此性能是一个严重的问题。 回答1 如果性能是一个严重的问题,那么您应该使用内在函数/内建函数来使用特定于CPU的指令,例如在此处为GCC找到的指令: http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Other-Builtins.html 内置函数int __builtin_ffs(unsigned int x) 。 返回1加x的最低有效1位的索引,或者如果x为零,则返回零。 内置函数int __builtin_clz(unsigned int x) 。 从最高有效位位置开始,返回x中前导0位的数目。 如果x为0,则结果不确定。 内置函数int __builtin_ctz(unsigned int x) 。 从x的最低有效位位置开始,返回x中的尾随0位的数目。 如果x为0,则结果不确定。 诸如此类的事情是许多O(1)算法的核心
  • 为什么plyr这么慢?(Why is plyr so slow?)
    问题 我认为我使用plyr的方式不正确。 有人可以告诉我这是否是“高效”的plyr代码吗? require(plyr) plyr <- function(dd) ddply(dd, .(price), summarise, ss=sum(volume)) 有一点背景:我有一些大的聚合问题,并且我注意到它们每个都花一些时间。 为了解决这些问题,我对R中各种聚合过程的性能产生了兴趣。 我测试了几种汇总方法-发现自己整天都在等待。 当我终于得到结果时,我发现plyr方法与其他方法之间存在巨大差距-这使我认为我做错了什么。 我运行了以下代码(我以为在检查时会检查新的dataframe程序包): require(plyr) require(data.table) require(dataframe) require(rbenchmark) require(xts) plyr <- function(dd) ddply(dd, .(price), summarise, ss=sum(volume)) t.apply <- function(dd) unlist(tapply(dd$volume, dd$price, sum)) t.apply.x <- function(dd) unlist(tapply(dd[,2], dd[,1], sum)) l.apply <- function(dd
  • 是std :: ifstream明显慢于FILE吗?(Is std::ifstream significantly slower than FILE?)
    问题 我被告知,我的库比应该的慢,解析特定文件(文本文件,大小326 kb)的速度比原来慢了30倍以上。 用户建议,可能是我使用的是std::ifstream (大概是FILE )。 我宁愿不要盲目地重写,所以我认为我应该先在这里检查一下,因为我想这可能是瓶颈所在。 我正在逐个字符地读取字符,因此我正在使用的唯一功能是get() , peek()和tellg()/seekg() 。 更新: 我进行了概要分析,并获得了令人困惑的输出-gprof似乎并没有认为它花了这么长时间。 我重新编写了程序,首先将整个文件读入缓冲区,然后加速了大约100倍。 我认为问题可能出在了很长时间的tellg()/seekg()上,但由于某些原因,gprof可能无法看到它。 在任何情况下,即使对于此大小, ifstream似乎也不会缓冲整个文件。 回答1 我认为那不会有所作为。 特别是如果您按字符读取字符,则I / O的开销很可能会完全支配其他任何内容。 为什么一次读取一个字节? 您知道这是多么的低效吗? 对于326kb的文件,最快的解决方案很可能是立即将其读入内存。 std :: ifstream和C等效项之间的区别基本上是一个或两个虚函数调用。 如果每秒执行几千万次,则可能会有所不同,否则并非如此。 文件I / O通常太慢,以至于用来访问它的API并不重要。 更重要的是读/写模式。 许多搜索是不好的
  • 我可以将列表用作R中的哈希吗? 如果是这样,为什么会这么慢?(Can I use a list as a hash in R? If so, why is it so slow?)
    问题 在使用R之前,我使用了很多Perl。 在Perl中,我经常使用哈希,在Perl中,哈希的查找通常被认为是快速的。 例如,以下代码将用最多10000个键/值对填充哈希,其中键是随机字母,值是随机整数。 然后,它在该哈希中进行10000次随机查找。 #!/usr/bin/perl -w use strict; my @letters = ('a'..'z'); print @letters . "\n"; my %testHash; for(my $i = 0; $i < 10000; $i++) { my $r1 = int(rand(26)); my $r2 = int(rand(26)); my $r3 = int(rand(26)); my $key = $letters[$r1] . $letters[$r2] . $letters[$r3]; my $value = int(rand(1000)); $testHash{$key} = $value; } my @keyArray = keys(%testHash); my $keyLen = scalar @keyArray; for(my $j = 0; $j < 10000; $j++) { my $key = $keyArray[int(rand($keyLen))]; my $lookupValue =
  • Redis 与磁盘在缓存应用程序中的性能(Performance of Redis vs Disk in caching application)
    问题 我想在 python 中创建一个 redis 缓存,作为任何自尊的科学家,我做了一个基准测试来测试性能。 有趣的是,redis 的表现并不好。 Python 正在做一些神奇的事情(存储文件),或者我的 redis 版本非常慢。 我不知道这是因为我的代码的结构方式,还是什么,但我希望 redis 做得比它更好。 为了制作 redis 缓存,我将二进制数据(在本例中为 HTML 页面)设置为从文件名派生的密钥,有效期为 5 分钟。 在所有情况下,文件处理都是使用 f.read() 完成的(这比 f.readlines() 快约 3 倍,我需要二进制 blob)。 我的比较中是否缺少某些东西,或者 Redis 真的不匹配磁盘? Python 是否将文件缓存在某处,并每次都重新访问它? 为什么这比访问 redis 快这么多? 我在 64 位 Ubuntu 系统上使用 redis 2.8、python 2.7 和 redis-py。 我认为 Python 没有做任何特别神奇的事情,因为我创建了一个函数,将文件数据存储在一个 Python 对象中并永久生成它。 我对四个函数调用进行了分组: 读取文件 X 次 一个被调用以查看 redis 对象是否仍在内存中、加载它或缓存新文件(单个和多个 redis 实例)的函数。 一个创建生成器的函数,该生成器从 redis 数据库(具有单个和多个
  • MySQL慢查询日志简介与使用
    MySQL慢查询日志 是什么 MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中 具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思是运行10秒以上的语句。 由他来查看哪些SQL超出了我们的最大忍耐时间值,比如一条sql执行超过5秒钟,我们就算慢SQL,希望能收集超过5秒的sql,结合之前explain进行全面分析。 怎么用 说明 默认情况下,MySQL数据库没有开启慢查询日志,需要我们手动来设置这个参数。 当然,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件 开启 默认情况下slow_query_log的值为OFF,表示慢查询日志是禁用的, 可以通过设置slow_query_log的值来开启 SHOW VARIABLES LIKE '%slow_query_log%'; 使用set global slow_query_log=1开启了慢查询日志只对当前数据库生效, 如果MySQL重启后则会失效。 设置慢查询时间 全局 set global long_query_time=1 当前会话
  • MYSQL8.0优化
    MYSQL8.0优化 1.tmp_table_size优化 数据库连接突然增多到1000的问题,查看了一下,未有LOCK操作语句。但是明显有好多copy to tmp table的SQL语句,这条语读的时间比较长,且这个表会被加读锁,相关表的update语句会被排进队列。如果多执行几次这样的copyt to tmp table 语句,会造成更多的语句被阻塞。连接太多造成mysql处理慢。copy to tmp talbe 语句产生的原因是查询需要Order By 或者Group By等需要用到结果集时,参数中设置的临时表的大小小于结果集的大小时,就会将该表放在磁盘上,这个时候在硬盘上的IO要比内销差很多。所耗费的时间也多很多。另外Mysql的另外一个参数max_heap_table_size比tmp_table_size小时,则系统会把max_heap_table_size的值作为最大的内存临时表的上限,大于这个时,改写硬盘。 我们的mysql这两个参数为: tmp_table_size 33554432 (33.5M) max_heap_table_size 16777216 (16.7M) 比较小。 建议增加到上百M。我们的内存应该够吧。 2.tmp_table_size优化 通过设置tmp_table_size选项来增加一张临时表的大小,例如做高级GROUP
  • 从Oracle迁移到MySQL(Migrate from Oracle to MySQL)
    问题 我们的Oracle数据库遇到了严重的性能问题,我们想尝试将其迁移到基于MySQL的数据库(直接使用MySQL,或者最好使用Infobright)。 关键是,在我们实际上不知道新数据库的所有功能是否符合我们的需求之前,我们需要让旧系统和新系统至少重叠数周(如果不是几个月)。 因此,这是我们的情况: Oracle数据库由多个表组成,每百万行。 白天,实际上有成千上万条语句,我们无法停止迁移。 每天早晨,新数据都会导入到Oracle数据库中,从而替换成千上万行。 复制此过程不是问题,因此从理论上讲,我们可以并行导入两个数据库。 但是,挑战就在这里,要使此工作正常进行,我们需要从一天开始就以一致的状态从Oracle数据库进行导出。 (我们不能在星期一导出某些表,而在星期二不能导出其他表,等等。)这意味着,至少导出应在不到一天的时间内完成。 我们的第一个想法是转储架构,但是我找不到能够将Oracle转储文件导入MySQL的工具。 将表格导出为CSV文件可能会起作用,但恐怕可能会花费太长时间。 所以我现在的问题是: 我应该怎么办? 是否有将Oracle转储文件导入MySQL的工具? 有人有过大规模迁移的经验吗? PS:请不要建议使用Oracle性能优化技术,我们已经尝试了很多:-) 编辑:我们已经尝试过一些ETL工具,才发现它们不够快:仅导出一张表已经花费了4个多小时... 第2编辑
  • 为什么as.Date在字符向量上很慢?(Why is as.Date slow on a character vector?)
    问题 我开始在R中使用data.table包来提高代码的性能。 我正在使用以下代码: sp500 <- read.csv('../rawdata/GMTSP.csv') days <- c("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday") # Using data.table to get the things much much faster sp500 <- data.table(sp500, key="Date") sp500 <- sp500[,Date:=as.Date(Date, "%m/%d/%Y")] sp500 <- sp500[,Weekday:=factor(weekdays(sp500[,Date]), levels=days, ordered=T)] sp500 <- sp500[,Year:=(as.POSIXlt(Date)$year+1900)] sp500 <- sp500[,Month:=(as.POSIXlt(Date)$mon+1)] 我注意到,与创建工作日等的其他函数相比,由as.Date函数完成的转换非常慢。为什么? 是否有更好/更快的解决方案,如何转换为日期格式? (如果您要问我是否真的需要日期格式,可能是,因为然后使用ggplot2进行绘制
  • 为什么R匹配功能这么慢?(Why is the R match function so slow?)
    问题 以下应该找到整数1的第一个实例的位置: array <- rep(1,10000000) system.time(match(1,array)) 这返回 user system elapsed 0.720 1.243 1.964 如果我使用大小为100的数组运行相同的任务,则会得到以下信息: user system elapsed 0 0 0 由于它要做的只是查看数组中的第一个值并返回一个匹配项,因此,无论数组大小如何,所需的时间应为查找和比较的时间。 如果我用较低级的语言编写此代码,则无论数组大小如何,其成本都将达到几个时钟周期(微秒或更短?)的数量级。 为什么在R中花一秒钟? 似乎遍历了他的整个数组。 一旦找到匹配项,是否有办法中止它,而不是继续进行不必要的迭代? 回答1 原因是R实际上并没有进行线性搜索,而是建立了一个哈希表。 如果要搜索多个项目,则此方法有效,但仅搜索一个数字时,效果不佳。 这是该函数的概要分析: 如果要在数组中搜索单个整数,则“更好”的实现可以使用线性搜索。 我想那会更快。
  • 排序字典python 3(sorting dictionary python 3)
    问题 我正在研究python 3.2.2。 我花了3多个小时的时间才能按字典对字典进行排序。 我设法使它成为具有2个自变量成员的排序列表,但最终却无法使其成为排序字典。 这是我想的: myDic={10: 'b', 3:'a', 5:'c'} sorted_list=sorted(myDic.items(), key=lambda x: x[0]) 但是,无论如何,我都无法从此排序列表中选出一本字典。 我怎么做? 谢谢! 回答1 dict不会保持其元素的顺序。 您需要的是OrderedDict:http://docs.python.org/library/collections.html#collections.OrderedDict 编辑 用法示例: >>> from collections import OrderedDict >>> a = {'foo': 1, 'bar': 2} >>> a {'foo': 1, 'bar': 2} >>> b = OrderedDict(sorted(a.items())) >>> b OrderedDict([('bar', 2), ('foo', 1)]) >>> b['foo'] 1 >>> b['bar'] 2 回答2 适用于Python 3.7的现代,快速解决方案。 在Python 3.6的某些解释器中也可以使用。 TLDR
  • 在R中快速替换数据框中的值(Fast replacing values in dataframe in R)
    问题 我有一个150,000行的数据框,其中有2,000列包含值,有些是负数。 我将这些负值替换为0,但是这样做非常缓慢(〜60分钟或更长)。 df[df < 0] = 0 df[,1441:1453]看起来像(所有列/值都是数字): V1441 V1442 V1443 V1444 V1445 V1446 V1447 V1448 V1449 V1450 V1451 V1452 V1453 1 3 1 0 4 4 -2 0 3 12 5 17 34 27 2 0 1 0 7 0 0 0 1 0 0 0 0 0 3 0 2 0 1 2 3 6 1 2 1 -6 3 1 4 1 2 3 6 1 2 1 -6 3 1 -4 1 0 5 1 2 1 -6 3 1 -4 1 0 0 1 0 0 6 1 0 0 1 0 0 0 0 0 0 1 2 2 有没有一种方法可以加快这样的过程,例如,我正在做的事情是非常缓慢的,并且有更快的方法可以做到这一点? 谢谢。 回答1 尝试将df转换为矩阵。 df <- data.frame(a=rnorm(1000),b=rnorm(1000)) m <- as.matrix(df) m[m<0] <- 0 df <- as.data.frame(m) 回答2 创建m<0时,原始方法和当前答案都将创建一个与m (或df )大小相同的对象(矩阵方法更快,因为[<