CSV (Comma Separated Values)作为一种逗号分隔型值的纯文本格式文件,在实际应 用中经常用到, 如数据库数据的导入导出、数据分析中记录的存储等,因此很多语言都提供了对CSV文件处理的模块, Python也不例外,其模块csv提供了一系列与CSV处理相关的 API。
常见的API
我们先来看一下其中几个常见的API:
reader(csvfile[,dia]ect='excel'][, fmtparam])
,主要用于CSV
文件的读取, 返回一个reader
对象用于在CSV
文件内容上进行行迭代。
参数 csvfile
,需要是支持迭代(Iterator)的对象,通常对文件(file)对象或者列表(list)对象都是适用的,
并且每次调用next()
方法的返回值是字符串(string);
参数 dialect
的默认值为 excel
,与excel兼容;frntparam
是一系列参数列表,
主要用于需要覆盖默认的 Dialect
设置的情形,当 dialect
设置为 excel
的时候,默认 Dialect
的值如下:
class excle():
delimiter=',' #单个字符,用于分隔字段
quotechar='"' #用于特殊符号加引号,常见的引号为"
doublequote=True #用于控制quotechar符号出现的时候的表现形式
skipinitalspace=False #设置为true的时候delimiter后面的空格将会忽略
lineterminator="\r\n" #行结束符
quoting=QUOTE_MINIMAL #是否在字符段前加引号,QUOTE_MINIMAL表示仅当一个字段包 #含引号或者定义符号的时候才加引号
csv.writer(csvfile, dialect='excel', **fmtparams)
,用于写入CSV
文件。 参数同上。来看一个使用例子。
import csv
with open ('data.csv','wb' ) as csvfile:
csvwriter = csv.writer(csvfile, dialect='excel', delimiter="|", quotechar='"' , quoting=csv.QUOTE_MINIMAL)
csvwriter.writerow(["l/3/09 14:44","'Productl'","1200''", "Visa","BGouya"])
#写入行
#python2 可执行
csv.DictReader(csvfile,fieldnames=None,restkey=None,restval==None, dialect='excel', *args,**kwds)
, 同reader()
方法类似,不同的是将读入的信息映射到一个字典中去,其中字典的key
由fieldnames
指定, 该值省略的话将使用CSV文件第一行的数据作为key
值。如果读入行的字段的个数大于filednames
中指定的个数, 多余的字段名将会存放在restkey
中,而restval
主要用于当读取行的域的个数小于fieldnames
的时候, 它的值将会被用作剩下的key
对应的值。csv.DictWriter(csvfile, fieldnames , restval='', extrasaction='raise',dialeet='excel',*args, **kwds)
, 用于支持字典的写入。
import csv #DictWriter
with open('test.csv',"wb") as csv_file:
#设置列名称
FIELDS = ['Transaction_date','Product1','Price','Payment_Type']
writer = csv.DictWriter(csv_file, fieldnames=FIELDS)
#写入列名称
writer.writerow(dict(zip(FIELDS, FIELDS)))
d = ("'Transaction_date's'1/2/09 6:17* f'Product':'Productl','Price*:'1200\ ayment_Type V: 'Mastercard'")
with open ('test.csv','rb') as csv_file:
for d in csv. DictReader (csv_file):
print (d)
#python2 内执行
import csv
f=open("large.csv","wb")
f.seek(1073741824-1)
f.write(b"\0")
f.close()
import os
os.stat("large.csv").st_size
#python2 内执行
with open("large.csv","rb") as csvfile:
mycsv=csv.reader(csvfile,delimiter=";")
for row in mycsv:
print( row)
上面的例子中当企图读入这个CSV文件的时候抛出了 MemoryError
异常 a
这是为什么?
因为 csv
模块对于大型CSV文件的处理无能为力。
这种情况下就需要考虑其他解决方案了,pandas
模块便是较好的选择。
Pandas即Python Data Analysis Library,是为了解决数据分析而创建的第三方工具, 它不仅提供了丰富的数据模型,而且支持多种文件格式处理,包括CSV、HDF5、HTML等, 能够提供高效的大型数据处理。其支持两种数据结构——Series和DateFrame——是数据处理的基础。 下面先来介绍这两种数据结构。
- Series:它是一种类似数组的带索引的一维数据结构,支持的类型与
NumPy
兼容。 如果不指定索引,默认为0
到N-1
,通过obj.values()
和obj.index()
可以分别获取值和索引。 当给Series
传递一个字典的时候,Series
的索引将根据字典中的键棑序。 如果传入字典的时候同时重新指定了index
参数,当index
与字典中的键不匹配的时候, 则会出现数据丢失的情况,标记为NaN
。
在pandas中用函数isnull()
和notnull()
来检测数据是否丢失。
import pandas
obj1=pandas.Series([1,'a',(1,2),3],index=['a','b','c','d'])
obj1
a 1 b a c (1, 2) d 3 dtype: object
obj2=pandas.Series({"Book":"Python","Author":"Dan","ISBN":"011334","Price":25},index
=["book","Author","ISBM","Price"])
obj2
book NaN Author Dan ISBM NaN Price 25 dtype: object
DataFrame
:类似于电子表格,其数据为排好序的数据列的集合, 每一列都可以是不同的数据类型,它类似于一个二维数据结构,支持行和列的索引。 和Series
一样,索引会自动分配并且能根据指定的列进行排序,使用最多的方式是通过一个长度相等的列表的字典来构建。 构建一个DataFrame最常用的方式是用一个相等长度列表的字典或NumPy
数组。 DataFrame也可以通过columns
指定序列的顺序进行排序。
data = {
'orderDate': ['1-6-10', '1-23-10', '2-9-10', '3-23-20', '3-19-10'],
'region': ['east', 'cesdf', 'asdcve', 'egedsa', 'east'],
'Rep': ['jones', 'kivell', 'aasdfj', 'gill', 'sorvion']
}
df = pandas.DataFrame(data, columns=['orderDate', 'region', 'Rep'])
保存为 xx_sampledata.csv
文件(默认保存在当前工作目录),
index=False
表示不保存行索引。
df.to_csv('xx_sampledata.csv', index=False)
df
orderDate | region | Rep | |
---|---|---|---|
0 | 1-6-10 | east | jones |
1 | 1-23-10 | cesdf | kivell |
2 | 2-9-10 | asdcve | aasdfj |
3 | 3-23-20 | egedsa | gill |
4 | 3-19-10 | east | sorvion |
df=pandas.read_csv("xx_sampledata.csv",nrows=2,usecols=['orderDate','region','Rep'])
df
orderDate | region | Rep | |
---|---|---|---|
0 | 1-6-10 | east | jones |
1 | 1-23-10 | cesdf | kivell |
函数 read_csv()
的参数 nrows
指定读取文件的行数,usecols
指定所要读取的列的列名,
如果没有列名,可直接使用索引0、1、...、n-1。上述两个参数对大文件处理非常有用,
可以避免读入整个文件而只选取所需要部分进行读取。
2)设置CSV文件与excel兼容。dialect
参数可以是 string
也可以是 csv.Dialect
的实例。
如果将文件格式改为使用“丨”分隔符,则需要设置 dialect
相关的参数。
error_badlines
设置为 False
,当记录不符合要求的时候,
如记录所包含的列数与文件列设置不相等时可以直接忽略这些列。
下面的代码用于设置CSV文件与excel兼容,其中分隔符为"|",
而 error_bad_lines=False
会直接忽略不符合要求的记录。
import csv
dia=csv.excel()
dia.delimiter="|"
pandas.read_csv("xx_sampledata.csv")
orderDate | region | Rep | |
---|---|---|---|
0 | 1-6-10 | east | jones |
1 | 1-23-10 | cesdf | kivell |
2 | 2-9-10 | asdcve | aasdfj |
3 | 3-23-20 | egedsa | gill |
4 | 3-19-10 | east | sorvion |
pandas.read_csv("xx_sampledata.csv", dialect=dia, on_bad_lines='skip')
orderDate,region,Rep | |
---|---|
0 | 1-6-10,east,jones |
1 | 1-23-10,cesdf,kivell |
2 | 2-9-10,asdcve,aasdfj |
3 | 3-23-20,egedsa,gill |
4 | 3-19-10,east,sorvion |
3)对文件进行分块处理并返回一个可迭代的对象。分块处理可以避免将所有的文件载入内存,
仅在使用的时候读入所需内容。参数 chimksize
设置分块的文件行数,10表示每一块 包含10个记录。
将参数 iterator
设置为 True
时,返回值为 TextFileReader
,它是一个可迭代对象,
来看下面的例子,当 chunk5ize=10
、iterator=True
时,每次输出为包含10个记录的块。
reader=pandas.read_table("xx_sampledata.csv",chunksize=10,iterator=True)
reader
<pandas.io.parsers.readers.TextFileReader at 0x7f37d9401c70>
iter(reader).next()# 将 TextFileReader 转换为送代器并调用 next 方法
0 l-6-10rEast# Jones,Pencilr 95r 1.99 , 189.05
1 l-23-10#CentralrKivell^Binder,50# 19.99 , 999.50
2 2-9-10#CentralrJardine,Pencilr36r 4.99 , 179.64
3 2-2-10rCentral,Gill#Pen,27# 19.99 , 539.73
4 3-15-10,WestrSorvinofPencilf56r 2.99 , 167.44
5 4-l-10rEast,JonesfBinderr60, 4,99 i 299.40
6 4-18-10,Central^ Andrews, Pencilf 75, K99 , 149.2S
7 5-5-10,CentraliJardine,Pencilr90, 4^99 , 449.10
8 5-22-10,West,Thompson,Pencil, 32, 1.99 , 63.68
9 6-8-10,East,Jones,Binderf 60, 8*99 j 539.40
4)当文件格式相似的时候,支持多个文件合并处理。 以下例子用于将3个格式相同的文件进行合并处理。
import os
filelst=os.listdir('/')
print(filelst)
['bin', 'boot', 'dev', 'etc', 'home', 'lib', 'lib64', 'media', 'mnt', 'opt', 'proc', 'root', 'run', 'sbin', 'srv', 'sys', 'tmp', 'usr', 'var', 'data']
os.chdir("test")
dfs=[pandas.read_csv(f) for f in filelst]
total_df=pandas.concat(dfs)
total_df
了解完 pandas
后,可以自行实验一下使用 pandas
处理前面生成的1GB的文件,
看着还会不会抛出 MemoryError
异常
在处理CSV文件上,特别是大型CSV文件,pandas不仅能够做到与csv模块兼容, 更重要的是其CSV文件以DataFirame的格式返回,pandas对这种数据结构提供了非常丰富的处理方法, 同时pandas支持文件的分块和合并处理,非常灵活,由于其底层很多算法采用 Cython实现运行速度较快。 实际上pandas在专业的数据处理与分析领域,如金融等行业已经得到广泛的应用。