使用pandas就要多用数组计算而不是循环计算 郝伟 2021/10/20 [TOC]
1. 前言
在处理数组数据时,传统的思维是使用循环。这本是很常规的操作,但是当我们在使用Pandas时(注:其实本质上还是numpy),使用其自身的计算方式会有极大的性能优势。下面我们来看这样的一个示例。
2. 示例
在本示例中,我们对一个包括10条数据的模板(包括id和score两个字段)进行1万次复制,复制完成后合并成一个单独的DataFrame,总数据量为10万行。由于模板中的id取值是0,1,2...,9,所以在复制以后,会有大量的重复的0-9的id。为了保证id的唯一性,现在重新对id进行统一编码,值的范围为0,1,2,..., 99998,99999。
2.1. 代码实现
在以下的代码中,使用了传统的循环做法和pandas可用的直接使用range赋值两种方法,并对时间进行测量。
# encoding=utf-8
'''
作者:郝伟老师
日期:2021/10/20
描述:pandas索引创建效率验证。
历史:
'''
import os, sys
import pandas as pd
import time
# 初始化模板
columns='id,score'.split()
values = [(0,5),(1,5),(2,5),(3,5),(4,5),(5,5),(6,5),(7,4),(8,4),(9,4)]
df = pd.DataFrame(values, columns = ['id', 'score'])
print(df)
# 复制10000次,并合并到一起,结果id就会有大量的重复
dfs= []
for _ in range(10000):
dfs.append(df)
result = pd.concat(dfs)
print('total: ', len(result))
# 使用两种方法进行顺序编号,并记录时间
t1 = time.time()
result['id'] = range(len(result)) # 方法1:使用直接使用Range
t2 = time.time()
for i in range(len(result)): # 方法2:使用iloc进行顺序遍历
result['id'].iloc[i] = i
t3 = time.time()
print("time1={0:.3f}, time2={1:.3f}".format(t2-t1, t3-t2))
2.2. 运行结果
代码运行后,输出时间如下。
time1=0.006, time2=19.581
3. 结论
根据以上实验,可以看出使用range方法只需要6毫秒就解决了需求,而使用iloc方法居然需要19.581秒,耗时为前者的3200多倍,差异巨大。产生的原因,应该是iloc在遍历时耗时比较多。
实际上,这个示例仅仅是pandas使用的一个缩影。pandas对数组操作进行了大量的优化,其提供的很多数组的操作方法的运行效率要远比传统的循环要高。所以在使用时,只要可以就使用pandas自带的数组操作方法。只有在真的没有办法的时候,再考虑传统的循环方法。