1 前言

Python的数据分析包Pandas具备读写csv文件的功能,read_csv 实现读入csv文件,to_csv写入到csv文件。每个函数的参数非常多,可以用来解决平时实战时,很多棘手的问题,比如设置某些列为时间类型,当导入列含有重复列名称时,当我们想过滤掉某些列时,当想添加列名称时...

这篇专题我们结合官方文档,带你全面了解这些常用的参数,真正用透这2个函数。实际上,通过这2个函数的学习,我们不光能理解透这两个函数,顺便还可以了解更多Pandas的知识点,下面开始我们的专题之旅。

2 read_csv

读入一个带分隔符的csv文件到DataFrame中,也支持遍历或文件分割为数据片(chunks).

下面是函数的原型:


read_csv(filepath_or_buffer, sep=',', delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, iterator=False, chunksize=None, compression='infer', thousands=None, decimal=b'.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, dialect=None, tupleize_cols=None, error_bad_lines=True, warn_bad_lines=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None)

2.1 基本参数

filepath_or_buffer: 数据输入路径,可以是文件路径,也可以是URL,或者实现read方法的任意对象。

sep: 数据文件的分隔符,默认为逗号。假如sep为None,python引擎会通过内置的 csv.Sniffer工具自动判断分隔符。

注意:如果分割字符长度大于1,且不是 '\s+', 启动python引擎解析。

举例: test.csv文件分割符为 '\t', 如果使用sep默认的逗号分隔符,读入后的数据混为一体。



In [4]: df = pd.read_csv('test.csv')


In [5]: df Out[5]: id\tname\tage0 1\t'gz'\t101 2\t'lh'\t12

此时,sep必须设置为 '\t',数据方可正确读入。再变换test.csv的分割符为两个空格,此时分隔符设置为 \s+ 就可以正确读入。



In [7]: df = pd.read_csv('test.csv',sep='\s+') In [8]: df Out[8]: id name age0 1 'gz' 101 2 'lh' 12


In [9]: df['id'] Out[9]: 0 11 2Name: id, dtype: int64

delimiter: 分隔符的另一个名字,与sep相似

delim_whitespace: 0.18版本后新加参数,默认为False, 设置为True时,表示分割符为空白字符,可以是一个空格,两个,或 \t等。

如下test.csv文件分隔符为两个空格时,设置delim_whitespace为True:



In [4]: df = pd.read_csv('test.csv',delim_whitespace=True)In [5]: df Out[5]: id name age0 1 'gz' 101 2 'lh' 12


In [6]: df['id'] Out[6]: 0 11 2Name: id, dtype: int64

2.2 列和索引位置、名称

header:设置导入数据框的列名称,默认为 'infer',注意它与 names参数的微妙关系。

names没有被赋值,header会被infer为0,即选取数据文件的第一行作为列名称; 当names被赋值,header没被赋值时会被infer为None. 官方文档就介绍了这些,但是,如果它们都不被赋值,行为header会被infer为0;如果都赋值,就会实现两个参数的组合功能。

假如我们的数据文件只有如下两行:



1 'gz' 102 'lh' 12

分别看下这几种情况:

1) names没有被赋值,header也没赋值:



In [9]: df = pd.read_csv('test.csv',delim_whitespace=True)


In [10]: df Out[10]: 1 'gz' 100 2 'lh' 12

2) names没有赋值,header被赋值,此处有使用陷阱,切记: 数据域开始于行header设置值后一个

如下,因为我们的文件一共就只有两行,所以当header设置为1后,数据域始于index等于2处,超出数据范围,所以得到Empty DataFrame.



In [22]: df=pd.read_csv('test.csv',delim_whitespace=True,header=1)


In [23]: df Out[23]: Empty DataFrameColumns: [2, 'lh', 12]Index: []

3) names被赋值,header没有被赋值,常用的模式:



In [15]: df = pd.read_csv('test.csv',delim_whitespace=True,names=['id','name','a ...: ge'])


In [16]: df Out[16]: id name age0 1 'gz' 101 2 'lh' 12

4) names和header都被设置:



In [26]: df = pd.read_csv('test.csv',delim_whitespace=True,names=['id','name','a ...: ge'],header=0)


In [27]: df Out[27]: id name age0 2 'lh' 12

index_col



In [32]: df = pd.read_csv('test.csv',delim_whitespace=True,names=['id','name','a ...: ge'],index_col='id')


In [33]: df Out[33]: name ageid 1 'gz' 102 'lh' 12

当index_col为多个元素时,生成一个多索引数据框:



In [34]: df = pd.read_csv('test.csv',delim_whitespace=True,names=['id','name','a ...: ge'],index_col=['id','name'])


In [35]: df Out[35]: ageid name 1 'gz' 102 'lh' 12

usecols 参数用于选取数据文件的某些列到数据框中,如下所示,原数据文件,我们只想使用id和age两列,那么我们可以为usecols参数赋值为['id','age']:



In [36]: df = pd.read_csv('test.csv',delim_whitespace=True,names=['id','name','a ...: ge'],usecols=['id','age'])


In [37]: df Out[37]: id age0 1 101 2 12

squeeze 参数用于当读入的数据文件只有一列时,直接压缩为Series对象,默认为False, 如下当我们只需要导入id列时,如果不设置,返回的也是DataFrame实例:



In [41]: df = pd.read_csv('test.csv',delim_whitespace=True,names=['id','name','a ...: ge'],usecols=['id'])


In [42]: df Out[42]: id0 11 2


In [43]: type(df) Out[43]: pandas.core.frame.DataFrame

但是,如果我们设置了squeeze为True后,返回的就是Series对象,如下:



In [38]: df = pd.read_csv('test.csv',delim_whitespace=True,names=['id','name','a ...: ge'],usecols=['id'],squeeze=True)


In [39]: df Out[39]: 0 11 2Name: id, dtype: int64


In [40]: type(df) Out[40]: pandas.core.series.Series

现实中的数据错综复杂,如果导入的数据含有相同名称的列,我们该怎么办?

为了高效地模拟重复列,我们使用极简的数据重现,还是原来的test.csv文件,我们故意将数据改造为如下:



id id age1 'gz' 102 'lh' 12

此时导入数据后,得到如下数据框:



In [44]: df = pd.read_csv('test.csv',delim_whitespace=True)


In [45]: df Out[45]: id id.1 age0 1 'gz' 101 2 'lh' 12

可以看到某个列名称自动变为id.1,控制这个行为的为参数 mangledupecols, 它默认为True. 如果设置为False,我们看看会发生什么,会抛不支持的异常:



ValueError: Setting mangle_dupe_cols=False is not supported yet

但是官方文档中说明是这样的:Passing in False will cause data to be overwritten if there are duplicate names in the columns. 此处可能是Pandas包的问题,一回看看。

还有一个 prefix 参数比较有意思,当我们导入的数据没有header时,我们把此参数设置为my时,列自动变为my0, my1, my2,... 如下:



In [55]: df = pd.read_csv('test.csv',delim_whitespace=True,prefix='my',header=No ...: ne)


In [56]: df Out[56]: my0 my1 my20 id id age1 1 'gz' 102 2 'lh' 12

3 更多

read_csv 的其他参数还包括如下:

  1. 通用的解析框架
  2. NA和缺失值的处理
  3. 时间处理
  4. 迭代
  5. 文件压缩相关
  6. 错误处理
  7. 指定列的类型
  8. 指定列为 Categorical 类型
  9. 基于各种应用场景的参数灵活运用

接下来,还会介绍to_csv背后的故事。

一个函数,就是一场故事。