我有一个数据帧以多指标的表现基本上是一个二元矩阵:提高重复GROUPBY操作
day day01 day02
session session1 session2 session3 session1 session2 session3
0 1 0 0 0 0 0
1 0 0 1 1 1 0
2 1 1 1 0 0 1
3 1 0 0 1 0 0
4 1 0 1 0 0 0
从这个数据帧,我需要计算每日的资金用于每行:
day01 day02
0 1 0
1 1 2
2 3 1
3 1 1
4 2 0
并得到0,1秒的(值计数)这笔金额的数目...:我需要做此F
0 2
1 5
2 2
3 1
或会话。每一行会议和:
session1 session2 session3
0 1 0 0
1 1 1 1
2 1 1 2
3 2 0 0
4 1 0 1
,并获得价值数:
0 5
1 8
2 2
为基准,这是df.groupby(level='day', axis=1).sum().stack().value_counts()
(和df.groupby(level='session', axis=1).sum().stack().value_counts()
)的结果。 DataFrame在模拟退火算法的每次迭代中都会发生变化,并重新计算这些计数。当我剖析代码时,我发现在groupby操作上花费了大量的时间。
我试着保存groupby对象,并在每次迭代中对这些对象进行总计,但改进大约为10%。下面的代码创建一个更大的数据帧(类似于一个我):
import numpy as np
import pandas as pd
prng = np.random.RandomState(0)
days = ['day{0:02d}'.format(i) for i in range(1, 11)]
sessions = ['session{}'.format(i) for i in range(1, 5)]
idx = pd.MultiIndex.from_product((days, sessions), names=['day', 'session'])
df = pd.DataFrame(prng.binomial(1, 0.25, (1250, 40)), columns=idx)
在我的电脑,以下两种方法分别以3.8S和3.38s。
def try1(df, num_repeats=1000):
for i in range(num_repeats):
session_counts = (df.groupby(level='session', axis=1, sort=False)
.sum()
.stack()
.value_counts(sort=False))
daily_counts = (df.groupby(level='day', axis=1, sort=False)
.sum()
.stack()
.value_counts(sort=False))
return session_counts, daily_counts
def try2(df, num_repeats=1000):
session_groups = df.groupby(level='session', axis=1, sort=False)
day_groups = df.groupby(level='day', axis=1, sort=False)
for i in range(num_repeats):
df.iat[0, 0] = (i + 1) % 2
session_counts = session_groups.sum().stack().value_counts(sort=False)
daily_counts = day_groups.sum().stack().value_counts(sort=False)
return session_counts, daily_counts
%time try1(df)
Wall time: 3.8 s
%time try2(df)
Wall time: 3.38 s
注意:函数中的循环仅用于计时。对于第二个函数,为了获得正确的时序,我需要修改DataFrame。
我目前正在研究另一种方法,直接反映DataFrame中的更改计数没有重新计算组,但我还没有成功。跟踪受影响的行并更新保存的数据帧结果变慢。
有没有办法提高这些groupby操作的性能?
是否在T elems的顺序窝产品很重要?另外,两个产出的指标是否重要? – Divakar
不,只要我知道有多少个0,1等,那么顺序(或哪个数据结构就包含这些信息)并不重要。我应该知道哪一个对应于0,哪一个对应于1。 – ayhan