随机测试数据生成 与 Pandas迭代方法性能对比

news/2024/12/2 12:41:10/

作者:小小明

Faker库生成测试数据

Faker库可以用来生成我们需要的测试数据,安装:

pip install Faker

生成示例:

from faker import Faker
fake = Faker("zh_CN")
fake.profile()
{'job': '驯兽师/助理驯兽师','company': '盟新网络有限公司','ssn': '620922197308261288','residence': '青海省凤兰市花溪杨路u座 985024','current_location': (Decimal('-39.1941315'), Decimal('94.196658')),'blood_group': 'B+','website': ['http://ca.cn/', 'https://shaomao.net/', 'http://68.cn/'],'username': 'chao88','name': '杨坤','sex': 'F','address': '浙江省兴城县西峰叶街C座 376696','mail': 'guiyingfu@gmail.com','birthdate': datetime.date(1951, 2, 3)}

faker 提供的Standard Providers包括:

addressdate_timepersoncredit_card
automotivefilephone_numbercurrency
bankgeoprofilelorem
barcodeinternetpythonmisc
colorisbnssn
companyjobuser_agent

文档链接:

https://faker.readthedocs.io/en/master/providers.html

于是我们可以通过以下代码批量生成数据:

import numpy as np
import pandas as pd
from faker import Fakerfake = Faker("zh_CN")
size = 1000
person_data = [(fake.name(), fake.address(), fake.phone_number())for _ in range(size)]
df = pd.DataFrame(person_data, columns=['name', 'adress', 'phone'])
df['age'] = np.random.randint(25, 55, size)
df

由于我们只对单列进行迭代,于是只需生成单列的数据,但数据量一定要够大,下面将生成500百万条姓名数据:

import numpy as np
import pandas as pd
from faker import Fakerfake = Faker("zh_CN")
size = 5000000
names = pd.Series([fake.name() for _ in range(size)])
names

经测试生成500万条数据耗时近四分钟。

这对于我来说,感觉还是太慢了,于是我决定换自己写的生成算法试试。

4秒生成500万条随机姓名数据

经过一番尝试写出了如下代码:

def fake_name(size):xing = '赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛' \'奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐费廉岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅皮卞齐康' \'伍余元卜顾孟平黄和穆萧尹姚邵湛汪祁毛禹狄米贝明臧计伏成戴谈宋茅庞熊纪舒屈项祝董梁杜阮蓝闵' \'席季麻强贾路娄危江童颜郭梅盛林刁钟徐邱骆高夏蔡田樊胡凌霍虞万支柯昝管卢莫经房裘缪干解应宗' \'丁宣贲邓郁单杭洪包诸左石崔吉钮龚程嵇邢滑裴陆荣翁荀羊於惠甄曲家封芮羿储靳汲邴糜松井段富巫' \'乌焦巴弓牧隗山谷车侯宓蓬全郗班仰秋仲伊宫宁仇栾暴甘钭厉戎祖武符刘景詹束龙叶幸司韶郜黎蓟薄' \'印宿白怀蒲邰从鄂索咸籍赖卓蔺屠蒙池乔阴鬱胥能苍双闻莘党翟谭贡劳逄姬申扶堵冉宰郦雍卻璩桑桂' \'濮牛寿通边扈燕冀郏浦尚农温别庄晏柴瞿阎充慕连茹习宦艾鱼容向古易慎戈廖庾终暨居衡步都耿满弘' \'匡国文寇广禄阙东欧殳沃利蔚越夔隆师巩厍聂晁勾敖融冷訾辛阚那简饶空曾毋沙乜养鞠须丰巢关蒯相' \'查后荆红游竺权逯盖益桓公万俟司马上官欧阳夏侯诸葛闻人东方赫连皇甫尉迟公羊澹台公冶宗政濮阳' \'淳于单于太叔申屠公孙仲孙轩辕令狐钟离宇文长孙慕容鲜于闾丘司徒司空丌官司寇仉督子车颛孙端木' \'巫马公西漆雕乐正壤驷公良拓跋夹谷宰父谷梁晋楚闫法汝鄢涂钦段干百里东郭南门呼延归海羊舌微生' \'岳帅缑亢况郈有琴梁丘左丘东门西门商牟佘佴伯赏南宫墨哈谯笪年爱阳佟第五言福'ming = '伟刚勇毅俊峰强军平保东文辉力明永健世广志义兴良海山仁波宁贵福生龙元全国胜学祥才发武新利清' \'飞彬富顺信子杰涛昌成康星光天达安岩中茂进林有坚和彪博诚先敬震振壮会思群豪心邦承乐绍功松善' \'厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏泽晨辰士以建家' \'致树炎德行时泰盛秀娟英华慧巧美娜静淑惠珠翠雅芝玉萍红娥玲芬芳燕彩春菊兰凤洁梅琳素云莲真环' \'雪荣爱妹霞香月莺媛艳瑞凡佳嘉琼勤珍贞莉桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶' \'怡婵雁蓓纨仪荷丹蓉眉君琴蕊薇菁梦岚苑筠柔竹霭凝晓欢霄枫芸菲寒欣滢伊亚宜可姬舒影荔枝思丽秀' \'飘育馥琦晶妍茜秋珊莎锦黛青倩婷宁蓓纨苑婕馨瑗琰韵融园艺咏卿聪澜纯毓悦昭冰爽琬茗羽希'xing = np.array(list(xing))ming = np.array(list(ming))names = pd.Series(np.random.choice(xing, size))names += np.random.choice(ming, size)names.loc[np.random.choice(names.index, size//2, False)] += np.random.choice(ming, size//2)names.loc[np.random.choice(names.index, size//50, False)] += np.random.choice(ming, size//50)return names

经测试生成500万条性能数据仅耗时4秒钟,比fake的4分钟快了60倍:

%time names = fake_name(5000000)
names
Wall time: 4.08 s
0           汝青
1           缑天
2           喻华
3          丘妍强
4           生香... 
4999995     全武
4999996     费舒
4999997    裴婷欢
4999998     葛芸
4999999     燕龙
Length: 5000000, dtype: object

测试Pandas的三种迭代的性能

Pandas内置的迭代器函数有很多,但看一眼就知道性能会很低,因为它们都会给跌带出来的每个元素封装一个Series对象,所以也不在本次测试的范围之内。

本次测试的目的是比较Series对象的str处理器、apply方法以及for循环迭代numpy数组的性能。

测试前,我们先随机取100万行数据加上空格:

t1 = np.random.choice(names.index, 1000000, False)
t2 = np.random.choice(names.index, 1000000, False)
names.loc[t1] += ' '
names.loc[t2] = ' '+names.loc[t2]

下面开始测试:

print("names.str.strip()")
%timeit names.str.strip()names.loc[t1] += ' '
names.loc[t2] = ' '+names.loc[t2]
print("names.apply(str.strip)")
%timeit names.apply(str.strip)names.loc[t1] += ' '
names.loc[t2] = ' '+names.loc[t2]
print("[name.strip() for name in names.values]")
%timeit [name.strip() for name in names.values]names.loc[t1] += ' '
names.loc[t2] = ' '+names.loc[t2]
print("[name.strip() for name in names]")
%timeit [name.strip() for name in names]

结果:

names.str.strip()
2.23 s ± 41.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
names.apply(str.strip)
1.44 s ± 28.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
[name.strip() for name in names.values]
1.1 s ± 20.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
[name.strip() for name in names]
1.5 s ± 23.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

可以看到str处理器的向量模式耗时最久,apply方法次之,列表生成式迭代numpy数组反倒是最快的,for循环直接迭代series对象比apply稍慢一点。

实际编码中,我们也会直接使用for循环,而不使用生成式,所以再单独测试for循环迭代numpy数组的性能:

tmp = names.copy()
%%timeit
result = []
for name in tmp.values:result.append(name.strip())
1.17 s ± 21.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

可以看到虽然比列表生成式慢了点,却依然比apply方法快。

结论

经过以上测试,可以确定for循环迭代numpy数组会比apply方法更快,比for循环直接迭代Series对象会比apply稍慢一点;一直被推荐的str向量化操作反倒速度是最慢的。

速度从快到慢排序:

for循环迭代numpy数组 > apply > for循环迭代Series对象 > str向量化 > for循环迭代Series内置迭代器函数


http://www.ppmy.cn/news/633841.html

相关文章

分组加密是什么

在密码学中,分组加密(Block cipher),又称分块加密或块密码,是一种对称密钥算法。它将明文分成多个等长的模块(block),使用确定的算法和对称密钥对每组分别加密解密。分组加密是极其重要的加密协议组成,其中典型的如 AE…

SSM项目之短信验证码登录

第一步登入网站 zz短信平台 http://sms_developer.zhenzikj.com/zhenzisms_user/login.html 导入pom依赖 <dependency><groupId>com.zhenzikj</groupId><artifactId>zhenzisms</artifactId><version>2.0.2</version></dependen…

分组密码算法与DES算法

目录 1 分组密码的含义 1.1 分组密码介绍 1.2 分组密码的含义 1.3 分组密码的要求 2 分组密码的设计思想 2.1 分组密码的设计思想 3 分组密码的基本特点 3.1 分组密码的基本特点 3.2 分组密码的迭代结构 3.3 子密钥的生成方法 3.4 轮函数的设计准则 3.5 迭代的轮数 4…

Android JNI 进阶(含完整 Demo)

GetObjectArrayElement解释: 在JNI 中只有基本类型和引用类型,String 是引用类型,所以遍历 String[]的时候,采用GetObjectArrayElement()来接收 参数一:jobjectArray:所有的元素参数二:jsize:当前的位置 ReleaseIntArrayElements解释: ReleaseIntArrayElements()方法是 C通…

Java多线程导出Excel表格, 100w数据量

海量数据报表导出 背景 大数据量的报表导出&#xff0c;单线程的情况下&#xff0c;很大概率会导致OOM问题&#xff0c;而且导出时间长。 解决方法&#xff1a;多线程导出报表 多线程的优势就是可以同时处理多个任务&#xff0c;提高效率&#xff0c;减少接口的响应时间。…

《图解密码技术》笔记

《图解密码技术》是一本非常适合新手密码学入门的书籍&#xff0c;对于密码学相关的概念讲解的的非常清楚到位。本文是本人阅读该书做的笔记&#xff0c;供大家参考&#xff0c;不足之处&#xff0c;请批评指正。 第一部分 密码 第一章 环游密码世界 公钥密码&#xff08;pub…

2022年券商行业发展和产品研究报告

第一章 行业概况 证券行业指专门从事有价证券买卖的法人企业。分为证券经营公司和证券登记公司。狭义的证券公司是指证券经营公司&#xff0c;是经主管机关批准并到有关工商行政管理局领取营业执照后专门经营证券业务的机构。它具有证券交易所的会员资格&#xff0c;可以承销发…

MySQL随机生成customers表姓名,密码,性别,出生日期,电话,邮箱,收货地址,客户等级创建账号时间(function函数)

在设计图书书店数据库的customers客户表时,记录一些花了时间的成果。 首先创建客户表 drop table if exists customers; create table customers(customerid BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,customername varchar(50) not null COM…