回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<p>我想找到一种更有效的方法(在峰值内存使用率和可能的时间方面)来完成panda的<code>groupby.ngroup</code>工作,这样在处理大型数据集时就不会遇到内存问题(下面我提供了为什么本专栏对我有用的原因)。以一个小数据集为例。我可以使用<code>groupby.ngroup</code>轻松完成这项任务。你知道吗</p>
<pre><code>import pandas as pd
import numpy as np
df = pd.DataFrame(np.array(
[[0, 1, 92],
[0, 0, 39],
[0, 0, 32],
[1, 0, 44],
[1, 1, 50],
[0, 1, 11],
[0, 0, 14]]), columns=['male', 'edu', 'wage'])
df['group_id'] = df.groupby(['male', 'edu']).ngroup()
df
male edu wage group_id
0 0 1 92 1
1 0 0 39 0
2 0 0 32 0
3 1 0 44 2
4 1 1 50 3
5 0 1 11 1
6 0 0 14 0
</code></pre>
<p>但是当我开始使用更大的数据集时,内存使用和计算时间会爆炸,groupby中的内存使用与数据帧内存使用的比率在<code>N=100,000,000</code>比<code>N=100,000</code>增加了近三倍。见下文。你知道吗</p>
<pre><code>from memory_profiler import memory_usage
import time
N_values = [10**k for k in range(4, 9)]
stats = pd.DataFrame(index=N_values, dtype=float, columns=['time', 'basemem', 'groupby_mem'])
for N in N_values:
df = pd.DataFrame(
np.hstack([np.random.randint(0, 2, (N, 2)), np.random.normal(5, 1, (N, 1))]),
columns=['male', 'edu', 'wage']
)
def groupby_ngroup():
df.groupby(['male', 'edu']).ngroup()
def foo():
pass
basemem = max(memory_usage(proc=foo))
tic = time.time()
mem = max(memory_usage(proc=groupby_ngroup))
toc = time.time() - tic
stats.loc[N, 'basemem'] = basemem
stats.loc[N, 'groupby_mem'] = mem
stats.loc[N, 'time'] = toc
stats['mem_ratio'] = stats.eval('groupby_mem/basemem')
stats
time basemem groupby_mem mem_ratio
10000 0.037834 104.781250 105.359375 1.005517
100000 0.051785 108.187500 113.125000 1.045638
1000000 0.143642 128.156250 182.437500 1.423555
10000000 0.644650 334.148438 820.183594 2.454549
100000000 6.074531 2422.585938 7095.437500 2.928869
</code></pre>
<p>为什么我对这个组标识符感兴趣?因为我想创建使用pandas <code>groupby</code>函数的列,比如使用<code>.map</code>方法的<code>groupby.mean</code>,而不是占用大量内存和时间的<code>groupby.transform</code>。此外,<code>.map</code>方法可用于<code>dask</code>数据帧,因为<code>dask</code>当前不支持<code>.transform</code>。对于<code>"group_id"</code>列,我可以简单地执行<code>means = df.groupby(['group_id'])['wage'].mean()</code>和<code>df['mean_wage'] = df['group_id'].map(means)</code>来执行<code>transform</code>的工作。你知道吗</p>