pandas:计算时内存不足怎么办(eval和query)


前言

前面几篇文章笔者介绍了如何使pandas计算得到大幅提升,其中包括pandas快速处理字符串方法使用map、apply和applymap函数批量处理数据,并且比普通循环操作处理数据快500多倍,本文将谈及为pandas计算节省内存加速,希望能帮助大家。


提示:为方便快捷地解决问题,本文仅介绍函数的主要用法,并非全面介绍

一、eval()和query()的由来

numpy与pandas都是Python建立强大生态的基础库,他们的厉害之处是通过内置的方法将基本操作转换成C语言,numpy里面是向量化和广播运算,pandas则是分组型运算。便捷快速的同时带来的问题是常需要建立一个临时中间对象,这样做会占用大量的计算内存和时间,pandas的eval()和query()就是为解决此问题而生的,其中eval()函数还分pandas.eval()和pandas.DataFrame.eval():pandas.eval()可用于多个DataFrame之间的计算,pandas.DataFrame.eval()仅用于DataFrame中列之间的计算。

二、eval()的介绍

1.pandas.DataFrame.eval

DataFrame.eval(expr, inplace=False, **kwargs)

参数
expr:str;要计算的表达式字符串。
inplace:bool, 默认 False;设置是覆盖原DataFrame还是输出新的DataFrame。
**kwargs:可输入pandas.eval()的变量,后面详细说明。

返回ndarray, scalar或者pandas数据类型

下面是例子:
先创建一个DataFrame

import pandas as pd
import numpy as np
import time

data = pd.DataFrame(np.random.rand(10000,2),columns=['A','B'])
data.head()
          A         B
0  0.161016  0.166286
1  0.859612  0.221388
2  0.814103  0.984277
3  0.776477  0.302750
4  0.996164  0.760127

使用普通方式进行计算A、B列之和并计算耗时

start = time.time()
result = data['A'] + data['B']
end = time.time()
print(str(end-start))
0.9478774070739746

使用DataFrame.eval()方法计算并计算耗时

start = time.time()
result = data.eval('A+B')
end = time.time()
print(str(end-start))
0.1408524513244629

可以看出比直接列相加快了6.7倍

提示:计算机环境不同,其计算速度的差距也不同,笔者的实验仅作为参考。

DataFrame.eval()还可以将计算结果放到新增到一列中:

data.eval('C = A+B',inplace=True)
data.head()
          A         B         C
0  0.161016  0.166286  0.327302
1  0.859612  0.221388  1.081000
2  0.814103  0.984277  1.798380
3  0.776477  0.302750  1.079227
4  0.996164  0.760127  1.756291

我们可以使用@方法将局部变量使用到计算之中

test_num = 100
result = data.eval('A + B + @test_num')
result.head()
0    100.327302
1    101.081000
2    101.798380
3    101.079227
4    101.756291
dtype: float64

2.pandas.eval

pandas.eval可以让多个DataFrame或Series进行计算。

pandas.eval(expr, parser=‘pandas’, engine=None, truediv=, local_dict=None, global_dict=None, resolvers=(), level=0, target=None, inplace=False)

主要参数
提示:参数过多,仅介绍我认为主要且常用的几个参数,如需全面了解请参考官方介绍

expr:str;要计算的表达式,该字符串只能包含Python表达式。

parser:{‘pandas’, ‘python’}, 默认‘pandas’;选择用pandas语法还是Python语法解析表达式,这里让它默认就行了。

target:object, optional, 默认None;选择要处理的目标。

inplace:bool, 默认 False;选择是否替换target所指定的对象。

下面是例子:
对于一个DataFrame

import pandas as pd
import numpy as np
import time

data = pd.DataFrame(np.random.rand(10000,2),columns=['A','B'])
result = pd.eval('data.A+data.B')
result.head()
0    1.265516
1    1.191837
2    1.443026
3    0.595921
4    1.442945
dtype: float64

对于不同的DataFrame(参考官方案例)

nrows, ncols = 20000, 100
df1, df2, df3, df4 = [pd.DataFrame(np.random.randn(nrows, ncols)) for _ in range(4)]
add_pd = pd.eval('df1 + df2 + df3 + df4')
add_pd.head()
         0         1         2     ...           97        98        99
0 -0.484481 -1.593759 -0.540393    ...    -0.688837 -1.212668  2.375383
1  2.846088 -0.053718  2.861517    ...    -0.514399 -0.520711  1.378200
2  1.034824 -1.387115 -1.056278    ...     0.017538 -0.339709  1.773171
3 -4.820074  3.141094 -0.829376    ...    -0.494888 -1.280396 -0.803026
4  0.950161  0.253045 -0.977115    ...     3.878627  3.171613 -0.349569

[5 rows x 100 columns]

三、query()的介绍

pandas.DataFrame.query()的作用是让DataFrame的查询节省内存,实际使用来看速度并没有使用普通方法快。

DataFrame.query(expr, inplace=False, **kwargs)

参数
expr:str;要计算的表达式。

inplace:bool;选择是修改数据还是返回修改后的副本数据。

下面是例子和对比情况

import pandas as pd
import numpy as np
import time

data = pd.DataFrame(np.random.rand(10000,2),columns=['A','B'])
data.head()
          A         B
0  0.941237  0.568980
1  0.191276  0.083936
2  0.612065  0.662790
3  0.985512  0.446884
4  0.033947  0.610931

筛选出A列和B列都小于0.5的数据

result = data.query('A < 0.5 and B < 0.5')
result.head()
           A         B
1   0.191276  0.083936
9   0.395155  0.495593
19  0.284068  0.399290
24  0.334158  0.301924
25  0.297931  0.326648

同样也可以用@方法调用局部变量

num = 0.5
result = data.query('A < @num and B < @num')
result.head()
           A         B
1   0.191276  0.083936
9   0.395155  0.495593
19  0.284068  0.399290
24  0.334158  0.301924
25  0.297931  0.326648

总结

当我们使用pandas对大量数据进行计算时难免会遇到内存不够和时间消耗太久的问题,使用eval和query方法可以很方便的解决此类问题,但是当我们的数据量不大时使用此方法并没有任何效果。后续笔者还会继续分享一些关于数据科学的方法和技巧,请大家多多关注∩__∩。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值