首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python读写csv文件专题教程(1)

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 参数表示为使用哪个或哪些列作为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  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背后的故事。

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


下一篇
举报
领券