盲区探索——Stata的读写极限
本文作者:罗天尧,新疆大学商学院
本文编辑:周一鸣
技术总编:方一卓
Stata and Python 数据分析
爬虫俱乐部Stata基础课程、Stata进阶课程和Python课程可在小鹅通平台查看,欢迎大家多多支持订阅!如需了解详情,可以通过课程链接(https://appbqiqpzi66527.h5.xiaoeknow.com/homepage/10)或课程二维码进行访问哦~爬虫俱乐部寒假特训课程开课了!课程学习中,大家学习热情日益高涨,精彩提问络绎不绝,面对大家的踊跃提问,我们爬虫俱乐部也及时解惑,详实回答,得到了大家的一致好评。其中,有位同学抛出了一个Stata导入文件的问题,秉着严谨科学的态度,我们不仅要回答这个问题,还要对其进行极限测试。
这里我们先生成一个200M的文件来进行测试,文件每列内容均是从1到n的数字。
实际测试最快的方法。
为了节约操作时间,我们先使用python的xlsxwriter模块,自动化生成测试用的xlsx文件,具体的实现代码如下(可依据设备配置调参):
# coding:utf-8
'''
excel的函数不会占用存储空间,但会拖累加载速度
模块效率对比:
openpyxl: 文件大小为110.75kb, 平均时间大约为570ms
xlwt: 文件大小为505.91kb,平均时间大约为440ms
XlsxWrite: 文件大小为109.28kb,平均时间大约为500ms,且能最大规模的写入信息
xlwt写入的行数有限制,因此对于较大的文件来说,XlsxWrite的速度较快一点
'''
#1.导包
import xlsxwriter #最大能够支持1048576行数据,16384列数据
import time
from tqdm import tqdm,trange
#2.定义对象
start=time.time()
workbook=xlsxwriter.Workbook('test2.xlsx') #占用过大可加,{'constant_memory': True}(即时写入,类似excel写入+保存的做法,释放内存)
worksheet=workbook.add_worksheet()
workbook.allow_zip64 = True #缺失会抛xlsxwriter.exceptions.FileSizeError异常
'''
zip64,对4G以上文件的压缩;溯源到xlsxwriter的workbook类导入的zipfile;会在workbook.close()的异常处理中执行
'''
bold=workbook.add_format({'bold':True}) #一个格式对象
clock_range=tqdm((i,k) for i in(i for i in range(5151)) for k in (k for k in range(16385))) #通过生成器降低内存占用
clock_range.set_description("正在生成")
#3.执行生成操作
for z in clock_range:
worksheet.write(z[0],z[1],z[0],bold)
workbook.close()
end=time.time()
print(f"生成用时:{end-start}")
另一种通过dataframe传入excel的方式。
import time
import pandas as pd
import numpy as np
start=time.time()
df = pd.DataFrame(np.random.randn(5150,16384))
df.to_excel("test2.xlsx")
end=time.time()
print(f"生成用时:{end-start}")
Stata的实现代码短小精悍,但是耗时过长。
/*这里由于Stata导出时间过慢,我们只尝试生成了12000*900的数据集,生成的文件大小为138 MB,耗时1338.79s*/
clear
set maxvar 120000
set obs 120000
qui{
forvalues i = 1(1)900{
gen a`i'= `i'
forvalues x = 1(1)120000{
replace a`i'= `x' in `x'
}
}
}
export excel using "C:\Users\Administrator\Desktop\test_stata.xlsx"
本次测试使用的移动端配置:
正式测试开始,将数据导入Stata数据集。但stata导入excel文件的默认上限为40M ,如果超过这个上限,Stata会报错为“file could not be loaded”或“file too big”。
好在我们还可以通过help import_excel来查看帮助文件。Stata给出的解决方案有两种,一是选择分批导入数据;二是在命令框执行set excelxlsxlargefile on选项,设定开启大型excel导入选项。
之所以设置了导入excel上限是由于,Stata认为无约束的导入文件,会影响计算机的性能,导致计算机无法再完成额外的操作。具体来说,不论是Python、excel还是Stata,在进行读写操作时主要是占用内存空间。而在这种极端测试下,Stata或Python都会占满内存,导致计算机无法再为其他任务分配运行内存,进而会强制关闭其他进程、禁止开启进程,甚至是会结束系统进程,导致计算机卡死。
本次测试中,电脑的16G内存持续飘红,风扇呼啸,直至测试结束。下图为内存占用导致的问题。
set excelxlsxlargefile on
timer clear 2
timer on 2
import excel "D:\temp\test2.xlsx", sheet("Sheet1") clear //注意声明sheet
timer off 2
timer list 2
最终,Stata还是无法将整个excel导入。导入的结果为,在excel的5150*16384格式中,只导入了5150行2627列的数据;如果算上缺失值的话,那么Stata导入了1048576行2627列数据。
这里手动调用timer计时器,计时单位为秒,相当于此次不完全导入测试文件,花费了约一个半小时的时间。
关于r(3900)的报错问题,我们在Stata官方的操作笔记中查到,报错意为:数据内容超过了Mata矩阵的存储空间,且没有内存再能为其分配。
随后我们开始尝试将数据导出。首先将文件到出为Stata的dta格式。
timer clear 1
timer on 1
save "C:\Users\Administrator\Desktop\test.dta"
timer off 1
timer list 1
可以看出,导出的时间相较于导入还是有明显提升的。但是右键打开生成的文件可以发现,这个文件被放大至了20G左右。
进一步,我们测试主流的csv文件。csv是一种纯文本格式,在各个软件中的可读性都较强。
timer clear 5
timer on 5
export delimited using "D:\temp2\test.csv", replace
timer off 5
timer list 5
导出的速度与dta文件类似。
占用空间约为dta格式的十分之一。
再次尝试导入dta文件。相较于导入excel,速度已经有了较大提升。
timer clear 3
timer on 3
use "C:\Users\Administrator\Desktop\test.dta", clear
timer off 3
timer list 3
timer clear 6
timer on 6
import delimited "D:\temp2\test.csv", clear
timer off 6
timer list 6
由于Stata对excel格式的导出变量数量有限制,我们暂未测试其导出(写入)时间。前期通过python写入200M的excel文件,花费了约七分半(181 s(生成)+280.62s(写入));Stata生成的138M的excel文件,约为22分钟(1338.79s)。
从实验结果可以看出,excel的读取能力确实是乏善可陈,但其胜在文件精简,这可能来源于excel内置的动态压缩功能。例如,我们办公时对excel增量写入,保存后的文件占用可能小于原文件。为此我们进行了一个小测试:我们制作了两份相同的excel数据,当将二者合并时,新文件占用空间总是小于原文件占用空间的。除此之外,前文python代码对allow_zip64传入的参数(出现4G以上文件时会调用zip64,发生在文件保存关闭时),似乎也是在佐证这一点。
从读写速度来看,dta与csv格式文件还是具有相当优势的,尤其是最通用的csv格式。
当我们使用clear all命令后,一切都回归于平静。
为进一步明晰Stata对不同格式文件的读写能力、空间占用问题,本文选取了一份文本分析数据集用以进行进一步检验,其中包含了int、strl等多种变量格式。
use "C:\Users\Administrator\Desktop\管理层讨论.dta"
des
从结果可以看出,我们的结论基本与前期一致:excel格式空间占用精简,但读写能力较差;dta与csv的空间占用较大,但写入能力优势明显。
值得注意的是,与前文结论相比,csv格式的读入能力出现了偏差。翻阅Stata的输出记录,我们发现了一些问题,Stata频繁的在输出没有报错的提示信息。这是由于csv是一种文本格式文件,存储的内容没有明显的分隔符,而我们测试的数据集中是存在大量文本信息的,Stata并没有很好的识别这些信息,导致在分割变量时耗用了大量时间,且读取的信息是完全错误的。
最终,我们在import_delimited的可选项下尝试了多种策略,Stata依然无法正确且成功的处理csv中的文本数据,同时Stata认为我们在挑战极限。
由于现行消费级的主板,暂支持16g的内存,因此我们还无法投入过多成本去完成这一实验。
注: memory_used 是Stata中数据集占用的内存,单位 GB;obs表示数据集中的观测值数量;width 表示一行观测值占用的字节数;24 ,Stata 建议预留24个字节缓冲。
但对于有更多内存的测试者来说,还可以从Stata的操作笔记中可以获悉一些有关Stata内存的信息:memory(显示内存分配详情及利用率),query memory(查看memory的设定范围),set max_memory 16g, permanently(将memory指定为16g)。
从help memory的文档中我们可以知晓,其实我们并不用对Stata的内存进行设置,他会默认动态的调整空间分配。但对于有32g内存以上的测试者来说,可以尝试设置segmentsize(内存分段,提升内存利用的连续性),niceness(呼吸值,动态释放内存),以便更出色地完成实验。
同时,在一封Stata17发布前的官方Q&A信我们得知,对于文件读取的压力,不仅来源于Stata的处理能力限制,还来源于操作系统、类似DLL动态库占用的限制。正是因为这些不确定性,导致Stata有时能完成大数据集的导入,而第二次则可能失败。当然Stata也在积极努力去减少动态库的使用与内存碎片,同时建议用户考虑减少不必要的数据。未来的测试者可以尝试削减系统潜在的占用,或通过虚拟内存来完成测试。
END
重磅福利!为了更好地服务各位同学的研究,爬虫俱乐部将在小鹅通平台上持续提供金融研究所需要的各类指标,包括上市公司十大股东、股价崩盘、投资效率、融资约束、企业避税、分析师跟踪、净资产收益率、资产回报率、国际四大审计、托宾Q值、第一大股东持股比例、账面市值比、沪深A股上市公司研究常用控制变量等一系列深加工数据,基于各交易所信息披露的数据利用Stata在实现数据实时更新的同时还将不断上线更多的数据指标。我们以最前沿的数据处理技术、最好的服务质量、最大的诚意望能助力大家的研究工作!相关数据链接,请大家访问:(https://appbqiqpzi66527.h5.xiaoeknow.com/homepage/10)或扫描二维码:
最后,我们为大家揭秘雪球网(https://xueqiu.com/)最新所展示的沪深证券和港股关注人数增长Top10。
对我们的推文累计打赏超过1000元,我们即可给您开具发票,发票类别为“咨询费”。用心做事,不负您的支持!
往期推文推荐
Camelot提取PDF表格:一页多表、多页一表
Stata绘图系列——条形图绘制
Python常见内置函数(一)Stata绘图系列——饼形图绘制【爬虫实战】深交所服务业年报数据“挂羊头卖狗肉”?
Python与excel交互--xlsxwriter模块cnmapsearch——离公司最近的快餐店在哪
Python中的异常处理 Python交互式数据可视化——酷炫的Altair库 hk系列命令(3)—— hktrade hk系列命令(2)—— hkar hk系列命令(1)—— hkstock 超好用的字符串方法 基于Python的假设检验实现Stata与MySQL交互--基础操作 Jupyter Notebook中的魔术命令《Stata正则表达式》由中国金融出版社出版发行 匿名函数lambda到底怎么用?关于我们
微信公众号“Stata and Python数据分析”分享实用的Stata、Python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。
武汉字符串数据科技有限公司一直为广大用户提供数据采集和分析的服务工作,如果您有这方面的需求,请发邮件到statatraining@163.com,或者直接联系我们的数据中台总工程司海涛先生,电话:18203668525,wechat: super4ht。海涛先生曾长期在香港大学从事研究工作,现为知名985大学的博士生,爬虫俱乐部网络爬虫技术和正则表达式的课程负责人。
此外,欢迎大家踊跃投稿,介绍一些关于Stata和Python的数据处理和分析技巧。
投稿邮箱:statatraining@163.com投稿要求:1)必须原创,禁止抄袭;2)必须准确,详细,有例子,有截图;注意事项:1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。