这是在Pandas中分组的最快方法吗?
下面的代码运行得很好。我只是想确认一下:我使用Pandas的方式和计时是否正确,还有没有更快的方法?谢谢。
$ python3
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas as pd
>>> import numpy as np
>>> import timeit
>>> pd.__version__
'0.14.1'
def randChar(f, numGrp, N) :
things = [f%x for x in range(numGrp)]
return [things[x] for x in np.random.choice(numGrp, N)]
def randFloat(numGrp, N) :
things = [round(100*np.random.random(),4) for x in range(numGrp)]
return [things[x] for x in np.random.choice(numGrp, N)]
N=int(1e8)
K=100
DF = pd.DataFrame({
'id1' : randChar("id%03d", K, N), # large groups (char)
'id2' : randChar("id%03d", K, N), # large groups (char)
'id3' : randChar("id%010d", N//K, N), # small groups (char)
'id4' : np.random.choice(K, N), # large groups (int)
'id5' : np.random.choice(K, N), # large groups (int)
'id6' : np.random.choice(N//K, N), # small groups (int)
'v1' : np.random.choice(5, N), # int in range [1,5]
'v2' : np.random.choice(5, N), # int in range [1,5]
'v3' : randFloat(100,N) # numeric e.g. 23.5749
})
现在我会对5种不同的分组进行计时,每种分组重复两次,以确认计时结果。[我知道timeit(2)
会运行两次,但它报告的是总时间。我想分别知道第一次和第二次的时间。] 在这些测试中,Python大约使用了10G的内存,具体可以通过htop
查看。
>>> timeit.Timer("DF.groupby(['id1']).agg({'v1':'sum'})" ,"from __main__ import DF").timeit(1)
5.604133386000285
>>> timeit.Timer("DF.groupby(['id1']).agg({'v1':'sum'})" ,"from __main__ import DF").timeit(1)
5.505057081000359
>>> timeit.Timer("DF.groupby(['id1','id2']).agg({'v1':'sum'})" ,"from __main__ import DF").timeit(1)
14.232032927000091
>>> timeit.Timer("DF.groupby(['id1','id2']).agg({'v1':'sum'})" ,"from __main__ import DF").timeit(1)
14.242601240999647
>>> timeit.Timer("DF.groupby(['id3']).agg({'v1':'sum', 'v3':'mean'})" ,"from __main__ import DF").timeit(1)
22.87025260900009
>>> timeit.Timer("DF.groupby(['id3']).agg({'v1':'sum', 'v3':'mean'})" ,"from __main__ import DF").timeit(1)
22.393589012999655
>>> timeit.Timer("DF.groupby(['id4']).agg({'v1':'mean', 'v2':'mean', 'v3':'mean'})" ,"from __main__ import DF").timeit(1)
2.9725865330001398
>>> timeit.Timer("DF.groupby(['id4']).agg({'v1':'mean', 'v2':'mean', 'v3':'mean'})" ,"from __main__ import DF").timeit(1)
2.9683854739996605
>>> timeit.Timer("DF.groupby(['id6']).agg({'v1':'sum', 'v2':'sum', 'v3':'sum'})" ,"from __main__ import DF").timeit(1)
12.776488024999708
>>> timeit.Timer("DF.groupby(['id6']).agg({'v1':'sum', 'v2':'sum', 'v3':'sum'})" ,"from __main__ import DF").timeit(1)
13.558292575999076
这是系统信息:
$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 32
On-line CPU(s) list: 0-31
Thread(s) per core: 2
Core(s) per socket: 8
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 62
Stepping: 4
CPU MHz: 2500.048
BogoMIPS: 5066.38
Hypervisor vendor: Xen
Virtualization type: full
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 25600K
NUMA node0 CPU(s): 0-7,16-23
NUMA node1 CPU(s): 8-15,24-31
$ free -h
total used free shared buffers cached
Mem: 240G 74G 166G 372K 33M 550M
-/+ buffers/cache: 73G 166G
Swap: 0B 0B 0B
我认为这可能不太相关,但以防万一,上面的randChar
函数是为了处理mtrand.RandomState.choice
中的内存错误而做的一个变通方法:
1 个回答
4
如果你想安装iPython这个工具,你可以很方便地用%timeit来计时你的代码。安装好之后,你就不需要再输入python
来启动普通的Python解释器,而是输入ipython
。
接下来,你可以像在普通解释器中那样输入你的代码(就像你之前做的那样)。
比如,你可以输入:
%timeit DF.groupby(['id1']).agg({'v1':'sum'})
这样做的效果和你之前做的一模一样,不过如果你经常使用Python,我发现这样可以省下不少输入的时间 :).
iPython还有很多其他好用的功能,比如%paste
,我用这个来粘贴你的代码并进行测试,或者%run
来运行你保存在文件里的脚本,还有自动补全等功能。想了解更多,可以访问http://ipython.org/