楼主: gulongzhou
7055 34

[问答] 实测R的vector和list结构比python对应的list和dict慢近千倍,怎么破? [推广有奖]

  • 0关注
  • 0粉丝

高中生

7%

还不是VIP/贵宾

-

威望
0
论坛币
4 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
147 点
帖子
13
精华
0
在线时间
23 小时
注册时间
2013-6-8
最后登录
2020-12-25

楼主
gulongzhou 发表于 2016-1-5 10:08:00 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
求教各位大虾:
我用R处理一组数据,其中一部分的中间运算结果是形如(k1,v1),(k1,v2),(k2,v2),(k2,v3),(k1,v1)...的vector,不同vector间、vector内部的元素间都会有重复。现在我要整理K和V之间的对应关系,对应前面的例子,我要得到的结果是下面的list:(k1=c(v1,v2),k2=c(v2,v3)...)。假设k和v分别为要处理的一组(k,v)vector,lstResult是最终保留结果的list对象,我用R来处理的过程是:
#如果k在lstResult还没有出现,添加该组结果
if (length(lstResult[[k]]) == 0){
      lstResult[[k]] <- c(v)
    }
    #如果k在lstResult中已经出现过了,判断v是否出现在其对应的vector中,如果没有则添加进去
    else{
      if ((v %in% lstResult[[k]]) == FALSE){
        lstResult[[k]] <- append(lstResult[[k]], v)
      }
    }

程序很简单,但处理约50万组数据,在我64G内存的服务器上居然要花4~5个小时!
同样的实现过程,我把中间结果写入文件,然后用python的list和dict对象处理,文件读完后处理了不到2分钟就结束了。
由于我的预处理、建模都是用R来做的,如果整个用python实现一遍太麻烦;但每个中间结果都导出来用python处理,还得把处理后的结果在导出文件读入R,也不现实。
请大家看看是不是我什么地方没处理好?我觉得二者的性能不该有这么大的差距啊!
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:python Vector list IST ICT python 元素

沙发
soccy 发表于 2016-1-5 10:24:19
向量化或者用Rcpp改写循环部分。
已有 1 人评分论坛币 收起 理由
admin_kefu + 5 热心帮助其他会员

总评分: 论坛币 + 5   查看全部评分

藤椅
suimong 发表于 2016-1-5 11:43:19
根据经验判断题主的循环部分肯定是有改进余地的,应该尽可能采用vectorize的写法。题主可以提取一个1000组的数据样本做一下profile,看看时间都消耗在哪些语句上了。题主如果方便的话可以把数据样本上传一下,方便大家了解问题,文字描述还是不够解释清楚变量的结构。
已有 1 人评分论坛币 收起 理由
admin_kefu + 10 热心帮助其他会员

总评分: 论坛币 + 10   查看全部评分

板凳
cheetahfly 在职认证  发表于 2016-1-5 12:08:31
用R抽样,提出思路、改进思路、完善思路,然后将思路让专业的程序员去用最可靠的方式实现,不管是C++,还是Python。
既然提出了这个问题,我也想在此发起讨论,本人学习R不是想成为程序猿,而是想成为专业量化分析师,用R可以让我紧跟最前沿的数据分析算法,也可以让我直接改进现有的算法来解决具体问题。总之,我是用R来发现思路,完善思路,而是不具体执行。
各位大神如何看待这个问题??

报纸
gulongzhou 发表于 2016-1-5 12:30:33
cheetahfly 发表于 2016-1-5 12:08
用R抽样,提出思路、改进思路、完善思路,然后将思路让专业的程序员去用最可靠的方式实现,不管是C++,还是 ...
我跟你的情况相反,我本人还算是半个程序员,偏预研类的岗位。我用R的初衷也是能够快速验证算法,至于后面的实现可以给更专业的程序员做。但是R处理循环的性能还是把我惊呆了,没准我应该主程序用python,然后在python里面调R?

地板
cheetahfly 在职认证  发表于 2016-1-5 12:32:37
gulongzhou 发表于 2016-1-5 12:30
我跟你的情况相反,我本人还算是半个程序员,偏预研类的岗位。我用R的初衷也是能够快速验证算法,至于后面 ...
仔细看了下您的程序,应该有很大的优化(向量化和并行运算)的余地。不过我还没完全搞懂要实现什么,能举个例子吗?

7
gulongzhou 发表于 2016-1-5 12:53:37
cheetahfly 发表于 2016-1-5 12:32
仔细看了下您的程序,应该有很大的优化(向量化和并行运算)的余地。不过我还没完全搞懂要实现什么,能举 ...
您好,实际上我有形如K<-C(k1,k2,k1,k2,k3,k4,k1....),V<-c(v1,v2,v2,v3,v3,v4,v1...)的两个vector,其中:
1. 两个vector的长度是相同的,且数据是按位置一一对应的,可以理解成有很多个(k,v)元组组成的向量;
2. K中的各个k值,和V中的各个v值,都有可能会重复出现,例如我给的例子中,k1,k2;v1,v2,v3就多次出现了;
3. 最终我要找到各个k都对应了哪些v,其中要把v中重复的去掉,然后放到一个list中;在list中用k值做命名,用v值组成的vector做内容。例如上面的例子会得到list(k1=c(v1,v2),k2=c(v2,v3),k3=c(v3),k4=c(v4)).
不知道我上面的解释清楚吗?

8
suimong 发表于 2016-1-5 12:56:06
gulongzhou 发表于 2016-1-5 12:30
我跟你的情况相反,我本人还算是半个程序员,偏预研类的岗位。我用R的初衷也是能够快速验证算法,至于后面 ...
R里不用vectorize的函数的话性能是很不济的。感觉你的程序逻辑并不复杂,可以先用data.frame处理最后合并为list。或者你可以换一种思路,因为相对来说R处理data frame的包最多,而且有像data.table这样性能很好的包;list的话作为万能容器在性能上就自然要打折扣了

9
cheetahfly 在职认证  发表于 2016-1-5 14:30:11
我不知道理解的对不对,如果不对请见谅:

我用以下两个随机数序列模拟k和v:
  1. k <- round(runif(500000, min = 0, max=1), digits = 2) * 100
  2. v <- round(runif(500000, min = 0, max=1), digits = 2) * 100
复制代码
各50万个0~100之间的随机整数,中间肯定不少重复的。重要的事情说三遍:是各50万个,各50万个,各50万个;
  1. x <- matrix(c(k,v), ncol = 2)  # 组成2列的矩阵,矩阵就是向量的一种。
  2. dim(x)  #看看数据维度
  3. [1] 500000      2   
  4. # 数据没有问题
复制代码
首先,我会先按第一列(即k),再按第二列(即v)同时排序(其实这一步似乎是多于的,不过我个人喜欢数据整整齐齐):
  1. xo <- x[order(x[,1],x[,2]),]     #xo代表x ordered,不是xo酱啊
复制代码
接下来这一步是最核心的,节约时间主要靠这个(应该是)用C编写的函数:
  1. xu <- unique.matrix(xo)                #xu代表x unique; 没想到unique.matrix()这么强大吧
  2. dim(xu)      #查一下矩阵缩减了多少
  3. [1] 10201     2
  4. #  干得不错
复制代码
接下来基本就是收尾工作啦:
  1. indexk <- unique(xu[,1])      #  用矩阵第一列建立索引
  2. lstResult <- vector(mode="list", length = length(indexk))     #  用vector()函数创造给定长度的list,这里是想说明,list是一种递归型向量
  3. names(lstResult) <- indexk    #赋名
  4. for (i in 1:length(indexk)) {
  5.     lstResult[[i]] <- xu[xu[,1]==indexk[i],2]
  6. }
  7. # 搞定
  8. str(lstResult)  # 检查一下
复制代码
最后,看看时间花费多少,在我的i3CPU上的成绩:
耗时.png
3秒多时间,应该可以接受吧?

因为时间关系,没有仔细验证过各个步骤,如果有不对的地方请提出来,大家讨论。

最后总结一下,您原来的程序应该带有很浓的“C语言的口音”(这是我在r-blogger上看到的一句话,觉得挺酷),你一开始就把一个k元素和一个v元素看成是一个小向量,这不是真正的向量化。应该吧k,v看成一整个大向量(matrix是向量的一种)来通盘考虑。以上是我的一点点心得吧。

已有 3 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
admin_kefu + 30 + 1 + 1 + 1 热心帮助其他会员
suimong + 5 + 5 精彩帖子
gulongzhou + 1 + 1 + 1 精彩帖子

总评分: 论坛币 + 30  学术水平 + 7  热心指数 + 7  信用等级 + 2   查看全部评分

10
gulongzhou 发表于 2016-1-5 15:36:39
cheetahfly 发表于 2016-1-5 14:30
我不知道理解的对不对,如果不对请见谅:

我用以下两个随机数序列模拟k和v:
@cheetahfly 给你点120个赞!!!
我本人确实算半个C/Python程序员(之所以说半个是因为coding不是我的主业,但少不了要做demo),对数据处理还没有建立起向量化的思想。
除了本帖里面的问题,我程序里面还有一些被我逐行处理数据的地方,有了你这段程序做启发,我大概知道该怎么改了。
我最近1,2个月才开始接触R,今后少不得向您请教。

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-2 23:26