8-Pandas扩展之Pandas提升性能的方法(eval()、query())
使用Pandas得到阿布分布功能进行运算是,经常需要创建临时对象,这样会占用很大的内存和使用较长的计算时间。pandas为了解决性能问题,引入了eval()和query()函数,他们都依赖Numexpr包,运算过程中不需要费力地配置中间数组。
一、使用Pandas.eval()实现高性能运算
1、pandas中的函数eval()能够将字符串对象转化为有效的表达式,进行求值运算并返回结果;
一般地,运算简单或DataFrame数据量较少之时不适用eval()函数,在DataFrame大于10000行时使用eval(),性能会得到明显提升。
>>>import numpy as np >>>import pandas as pd >>>nrows=20000 >>>nclos=200 >>>df1,df2,df3,df4 = [pd.DataFrame(np.random.randn(nrows,nclos)) for i in range(4)] >>>%timeit df1+df2+df3+df4 50.8 ms ± 3.11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) >>>%timeit pd.eval('df1+df2+df3+df4') 23.6 ms ± 888 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
其中:魔术命令%timeit可自动多次执行语句,产生一个较为精准的平均执行时间。
使用np.allclose()比较两个数组是否完全相同,结果为True表示eval函数计算结果与普通Pandas计算结果一致。
>>>np.allclose(df1+df2+df3+df4,pd.eval('df1+df2+df3+df4')) True
2、eval()支持的运算方式
eval()函数支持多种运算方式,如:算数运算、比较运算和布尔运算,同时也支持对象属性与索引的表达方式;
eval()函数目前还不支持函数条用,if条件语句,循环语句及更为复杂的运算。
3、DataFrame.eval()实现列间运算
>>>df.eval("sex=='female'and score_math>80") 0 False 1 True 2 True 3 False 4 True 5 False 6 False 7 False 8 False dtype: bool #新增列 >>> df.eval('sum_score = score_math + score_music',inplace=True) >>> df class sex score_math score_music sum_score 0 A male 95 79 174 1 A female 96 90 186 2 B female 85 85 170 3 C male 93 92 185 4 B female 84 90 174 5 B male 88 70 158 6 C male 59 89 148 7 A male 88 86 174 8 B male 89 74 163 #修改列 >>> df.eval('score_math = score_math +5') class sex score_math score_music sum_score 0 A male 100 79 174 1 A female 101 90 186 2 B female 90 85 170 3 C male 98 92 185 4 B female 89 90 174 5 B male 93 70 158 6 C male 64 89 148 7 A male 93 86 174 8 B male 94 74 163
4、DataFrame.eval()使用局部变量
通过@符号使用Python的局部变量,@符号表示其后紧随的是一个变量名称而不是列名称,如下:
>>> add = pd.Series([1,2,3,4,5,6,7,8]) >>> df.eval('score_math+@add') 0 96.0 1 98.0 2 88.0 3 97.0 4 89.0 5 94.0 6 66.0 7 96.0 8 NaN dtype: float64
二、DataFrame.query()方法
query()可以实现查询过滤的功能,其用于与DataFrame.eval()类似。
>>> df.query("score_math>85 & score_music>85") class sex score_math score_music sum_score 1 A female 96 90 186 3 C male 93 92 185 7 A male 88 86 174
注意:DtaFrame.eval()尽心相同运算时返回的是布尔值