performance - 根据一个列表对元素进行分组并将另一个列表中的相应条目相加
问题描述
问题:给定相同长度的整数列表uu,ww
,在 Python 3 中,我希望计算较短的列表 u,w 相同长度,其中 u=uu 的唯一元素,w[i]=所有 ww[j] 的总和,使得 uu[ j]=u[i],即对元素进行累加。例如,对于uu=[1,2,1,3,2,2,1,3,1,4]; ww=[0,4,2,1,6,3,2,6,3,0]
输出应该是[1,2,3,4],[7,13,7,0]
.
解决方案:我找到了这些方法来实现我的目标:
import numpy as np
import pandas as pd
import itertools, collections
def ti(): return time.perf_counter() #current time
def acml(method,uu,ww):
if method==1: #result is not sorted
d=collections.defaultdict(int)
for i in range(len(uu)): d[uu[i]]+=ww[i]
return list(d.keys()),list(d.values())
if method==2: #result is sorted
uw=list(zip(uu,ww)); #transposed list
uw.sort(key=lambda x:x[0]); #sorted by zeroth coordinate
uw=itertools.groupby(uw,lambda x: x[0]); #iterator
uw=[[k,sum([i[1] for i in v])] for k,v in uw];
return list(zip(*uw))
if method==3: #slow, result is sorted
x=pd.DataFrame(data={'u':uu,'w':ww}); x=x.groupby('u');
u=[i for i,xi in x]; w=[xi['w'].sum() for i,xi in x]; return u,w
n=10**5; r=n//2; uu=list(np.random.randint(0,r,size=n)); ww=list(np.random.randint(-10,10,size=n));
t0=ti(); uw1=acml(1,uu,ww); t1=ti(); print(t1-t0)
t0=ti(); uw2=acml(2,uu,ww); t1=ti(); print(t1-t0)
t0=ti(); uw3=acml(3,uu,ww); t1=ti(); print(t1-t0)
有没有更快的功能可以实现这一点?(元素的顺序无关紧要)
背景:我需要这个函数的原因acml
是我正在构建一个巨大的稀疏矩阵(大小高达 10^7 x 10^7,每列有几个条目)。我通过为每一列计算v
条目来做到这一点(u,w)
。通常,会出现多个具有相同第一个坐标的此类条目,因此应将这些元素的第二个坐标相加。
我意识到构造scipy.sparse.csr_matrix(ww,(uu,vv))
已经解决了这个问题(即它对属于同一位置的值求和),但我仍然想使用acml
,因为我的矩阵几乎不能放入内存中,所以累积每列的条目(在条目之前甚至找到其他列)将节省 RAM。
解决方案
推荐阅读
- php - 在 JavaScript 中获取 smarty 变量
- java - 使用 Java 邮件 API。javax.mail.MessagingException:无法确定本地电子邮件地址异常
- julia - 原子和键列表中分子的 2D 和/或 3D 图
- sql-server - sql server中的异常处理部分
- javascript - 如何同步 FileReader onload 函数?
- deep-learning - CycleGAN 用于未配对的图像到图像的转换
- node.js - 使用nodejs如何在循环中返回一个包含来自一批API调用的所有数据的对象?
- javascript - 即使在 subscribe() 函数中为其分配数据后,变量数据也不会保留在 HTML 中绑定
- ssl - Kubernetes 证书管理器 GoDaddy
- typescript - typescript:如何导出函数和接口