心路历程:发现小技巧->尝试->发现问题->试图解决问题->
1.原来read_csv还有这种功能
前几天参加美赛,在数据处理阶段需要合并100+的excel文档,想把这些工作簿都合并到一个工作簿的一个表单里面,我觉得这么麻烦一定有简单的方法(嗯【托腮】),于是去网上查,果然!于是就很happy的开始尝试~
主要看到两种方法,一种用excel自身的代码来合并,操作方法倒是比较简便,但是我尝试了一下,主要有以下 not practical 的地方:
1. 合并速度比较慢。(当时急着要数据,但是等了大概5min左右,还没合并好,而且最终合并还失败了,我还不知道原因。【吐血】)
2. 看不懂代码,没办法根据自己的需求来更改。【嘤嘤嘤】
3. 倒是把所有的工作簿合并到一个excel里面了,但是分成了不同的表单,没办法满足我需要同时处理的需求。【sigh】
第二种就比较厉害了,而且一次合并成功(●'◡'●)。是用python代码实现的。As following:
import pandas as pd
import os
Folder_Path = r'C:\Users\733\Desktop\dataA' #要拼接的文件夹及其完整路径,注意不要包含中文
SaveFile_Path = r'C:\Users\733\Desktop\dataA' #拼接后要保存的文件路径
SaveFile_Name = r'all.csv' #合并后要保存的文件名
#修改当前工作目录
os.chdir(Folder_Path)
#将该文件夹下的所有文件名存入一个列表
file_list = os.listdir()
#读取第一个CSV文件并包含表头
df = pd.read_csv(Folder_Path +'\\'+ file_list[0]) #编码默认UTF-8,若乱码自行更改
#将读取的第一个CSV文件写入合并后的文件保存
df.to_csv(SaveFile_Path+'\\'+ SaveFile_Name,encoding="utf_8_sig",index=False)
#循环遍历列表中各个CSV文件名,并追加到合并后的文件
for i in range(1,len(file_list)):
df = pd.read_csv(Folder_Path + '\\'+ file_list[i])
df.to_csv(SaveFile_Path+'\\'+ SaveFile_Name,encoding="utf_8_sig",index=False, header=False, mode='a+')
代码源自:https://blog.csdn.net/kxw1994/article/details/76465152
我抱着试一试的态度试了一下,哈!好好用,一次成功,运行比较快,不过似乎中间也报错过几次,似乎不能合并不同名称的文档?
2.为什么会报错?
当时为什么会报错以及报的什么错我已经无从考证辽orz,没有存报错记录。但是我可以再模拟一遍当时的过程嘛!
比赛完的今天我决定再试一次,用两种不同名称类型的文档。然而当我仔细地分析了一下语句之后发现,我当时没合并完应该只是下载的数据文件本身的问题。代码是用length来合并的,不可能跟文件名称有关系。但是我二话不说还是拿原来的数据集进行了一波没有什么卵用的实验。
然后,,我发现了一个可怕的事实呜呜呜,我当时急着合并,没有严谨仔细地检查不同经纬度区域的数据的表头,里面从BB后面的数据表头是不一样的。怪不得程序提示我这个:DtypeWarning: Columns (62,63,64,65) have mixed types. Specify dtype option on import or set low_memory=False.不过还好我们用到的那部分数据我当时check了一下发现是一样的。
作为一个好奇宝宝,我开始探索warning的后半部分是什么意思。经过自己的思考和查找,报错的意思是,第(62,63,64,65) 列的数据类型不一致。我去看了下这几列(BJ:BM)的数据类型,发现确实不一致,有0有A,(有int 有char)不过这后几列对我也没用2333,我决定不再管这个数据,去研究一下怎么处理这类情况好啦。
3.如何处理?
Method 1:设置read_csv的dtype参数,指定字段的数据类型
也就是warning里面提示的Specify dtype option。设置方法:dtype={'colname':object}
尝试结果: 我把循环中的语句中的其中一列(63列)的类型改为str,代码见下:
df = pd.read_csv(Folder_Path + '\\'+ file_list[i],dtype={'ICE_OF_LAND_ORIGIN':object})
于是报错就变成了:Columns (62,64,65) have mixed types. Specify dtype option on import or set low_memory=False.说明第63列更改有效~
另外read_csv中其他参数的设置方法可见:
https://zhuanlan.zhihu.com/p/76489045
https://blog.csdn.net/Luckyzhou_/article/details/69062261
Method 2:关闭low_memory模式 ,即设置low_memory=False
原因:
low_memory默认是True,意思是pandas读取csv文件按块读取,这是为了在解析时减少了内存使用。pandas对数据的类型是完全靠猜的,pandas每读取一块数据就对csv字段的数据类型进行猜一次,所以有可能pandas在读取不同块时对同一字段的数据类型猜测结果不一致。
low_memory=False 参数设置后,pandas会一次性读取csv中的所有数据,然后对字段的数据类型进行唯一的一次猜测。这样就不会导致同一字段的Mixed types问题了。
However!这个方法有个致命缺点:一旦csv文件过大,就会内存溢出。so 推荐使用第一种。
4.折腾了很久之后的思考
在看函数的各种参数的过程中我发现自己的python语法知识实在是太...差辽QAQ。明确了我这些天要好好复习一下基础知识,把基础打牢才能上技术炫技吖。
其次就是看函数参数的官方介绍的时候很多地方看得似懂非懂,而且看到英语就产生很不想看进去的感觉,嘤嘤嘤。我还是英语水平太差了,还是得多读读英语多背背单词。