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\tage
0 1\t'gz'\t10
1 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 age
0 1 'gz' 10
1 2 'lh' 12
In [9]: df['id']
Out[9]:
0 1
1 2
Name: 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 age
0 1 'gz' 10
1 2 'lh' 12
In [6]: df['id']
Out[6]:
0 1
1 2
Name: id, dtype: int64
2.2 列和索引位置、名称
header:设置导入数据框的列名称,默认为 'infer'
,注意它与 names
参数的微妙关系。
当names没有被赋值,header会被infer为0,即选取数据文件的第一行作为列名称; 当names被赋值,header没被赋值时会被infer为None
. 官方文档就介绍了这些,但是,如果它们都不被赋值,行为header会被infer为0;如果都赋值,就会实现两个参数的组合功能。
假如我们的数据文件只有如下两行:
1 'gz' 10
2 'lh' 12
分别看下这几种情况:
1) names没有被赋值,header也没赋值:
In [9]: df = pd.read_csv('test.csv',delim_whitespace=True)
In [10]: df
Out[10]:
1 'gz' 10
0 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 DataFrame
Columns: [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 age
0 1 'gz' 10
1 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 age
0 2 'lh' 12
index_col 参数表示为使用哪个或哪些列作为index, 如下所示,数据文件还是只含有两行数据的test.csv,当我们设置index_col为id列时,就会生成一个index为id列的,columns只含有两列的数据框:
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 age
id
1 'gz' 10
2 '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]:
age
id name
1 'gz' 10
2 '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 age
0 1 10
1 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]:
id
0 1
1 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 1
1 2
Name: id, dtype: int64
In [40]: type(df)
Out[40]: pandas.core.series.Series
现实中的数据错综复杂,如果导入的数据含有相同名称的列,我们该怎么办?
为了高效地模拟重复列,我们使用极简的数据重现,还是原来的test.csv文件,我们故意将数据改造为如下:
id id age
1 'gz' 10
2 'lh' 12
此时导入数据后,得到如下数据框:
In [44]: df = pd.read_csv('test.csv',delim_whitespace=True)
In [45]: df
Out[45]:
id id.1 age
0 1 'gz' 10
1 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 my2
0 id id age
1 1 'gz' 10
2 2 'lh' 12
3 更多
read_csv 的其他参数还包括如下:
通用的解析框架
NA和缺失值的处理
时间处理
迭代
文件压缩相关
错误处理
指定列的类型
指定列为 Categorical 类型
基于各种应用场景的参数灵活运用
接下来,还会介绍to_csv背后的故事。
一个函数,就是一场故事。
本专题为 Python与算法社区 公众号出品,转载请注明出处。
Python与算法社区