python处理数据快吗_简单两步,大幅提高python数据处理速度

在数据分析领域,最热门的莫过于Python和R语言。其中,数据分析库pandas是Python最经典的库之一。它使用一个二维的DataFrame来表示表格式的数据,相比较于Numpy,Pandas可以存储混合的数据结构,同时使用NaN来表示缺失的数据,而不用像Numpy一样要手工处理缺失的数据,并且Pandas使用轴标签来表示行和列。

一般来说,用pandas处理小于100兆的数据,性能不是问题。但当我们要处理大量数据时,如何优化DataFrame的操作就需要仔细斟酌了。

例子

我们想象一个例子,你要处理一个csv文件,你想要把数据清洗后输出到另一个dataframe中,做后续处理。一个简单的程序如下:

# -*- coding: utf-8 -*-

import pandas as pd

import datetime as dt

indf = pd.read_csv('600369.csv', index_col = False, encoding = "gb2312")

output_index_num = 8000

outdf = pd.DataFrame(columns = indf.columns)

times1 = dt.datetime.now()

for outindex in range(0, output_index_num):

# have some fun here

outdf = outdf.append(indf.loc[int(len(indf) * outindex / output_index_num)],ignore_index=True)

times2 = dt.datetime.now()

print('Time spent: '+ str(times2-times1))

十分简单,不是吗?我们仅仅是把输入的dataframe(indf)扩展到输出outdf中去了。我们看一下运行时间:

Time spent: 0:01:58.830000

2分钟处理8000个单元,还行?这个远远不够,想象一下我们有10万个这样的csv要处理怎么办?那需要278天!怎么提高效能呢?

第一步

Dataframe的append效能很低,如果我们知道未来表的条目,预先分配好空间,将来直接向里面填入内容会快不少,我们来修改一下程序:

# -*- coding: utf-8 -*-

import pandas as pd

import datetime as dt

indf = pd.read_csv('600369.csv', index_col = False, encoding = "gb2312")

#outdf = pd.DataFrame(columns = indf.columns)

output_index_num = 8000

outdf = pd.DataFrame(pd.np.empty((output_index_num, len(indf.columns))) * pd.np.nan, columns = indf.columns)

times1 = dt.datetime.now()

for outindex in range(0, output_index_num):

# have some fun here

outdf.loc[outindex] = indf.loc[int(len(indf) * outindex / output_index_num)]

times2 = dt.datetime.now()

print('Time spent: '+ str(times2-times1))

结果好了不少:

Time spent: 0:01:27.636000

少了半分钟,是不是就这样了呢?还远远不够。

第二步

Dataframe检索每一行有好几个操作:loc,iloc,ix,at。它们效能有什么差别吗?我们来试一下:

%timeit outdf.loc[0] = indf.loc[0]

100 loops, best of 3: 11.7 ms per loop

%timeit outdf.iloc[0] = indf.iloc[0]

100 loops, best of 3: 11.4 ms per loop

%timeit outdf.ix[0] = indf.ix[0]

100 loops, best of 3: 11.6 ms per loop

%timeit outdf.at[0,'time'] = indf.at[0,'time']

10000 loops, best of 3: 25.3 µs per loop

loc,iloc,ix看起来速度都差不多,at可是快了将近1000倍啊,可惜的是at只能选择某个单元而不是整行。没关系,我们来改一下程序:

# -*- coding: utf-8 -*-

import pandas as pd

import datetime as dt

indf = pd.read_csv('600369.csv', index_col = False, encoding = "gb2312")

#outdf = pd.DataFrame(columns = indf.columns)

output_index_num = 8000

outdf = pd.DataFrame(pd.np.empty((output_index_num, len(indf.columns))) * pd.np.nan, columns = indf.columns)

times1 = dt.datetime.now()

outdf.loc[0] = indf.loc[0]

for outindex in range(0, output_index_num):

# have some fun here

for column in indf.columns:

outdf.at[outindex,column] = indf.at[int(len(indf) * outindex / output_index_num),column]

times2 = dt.datetime.now()

print('Time spent: '+ str(times2-times1))

结果大为改善:

Time spent: 0:00:07.850000

只有7秒,比以前快了12倍!更比开始的时候快了15倍多。

结论

如果目标数据集行数确定,我们应该先分配出来,在一项项填入而不是append,要做填空题而不是做补充题;尽量选择用at/iat而是不是方便的loc/iloc或者ix。

最后给大家一个思考题,为什么我在最后的程序里面加了个

outdf.loc[0] = indf.loc[0]

不加会怎么样?

人生苦短,我用Python;发财要早,我要量化!欢迎关注本专栏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值