Detailed read_csv method of pandas

wedge

Pandas NumPy Python-based and developed in the field of data analysis, it is widely used. The first step in using Pandas processing of data is often read in the data, such as reading and writing CSV files, and Pandas also provide strong support to read, as many as 38 parameters. These parameters, some easily overlooked, but it has proved very useful in practice. such as:

  • 文件读取时设置某些列为时间类型
  • 导入文件,含有重复列
  • 过滤某些列
  • 每次迭代读取 10 行

And when the pandas reading csv file read by read_csv function, let's take a good look at this function be born a look like, what are the parameters.

read_csv the parameters

The following are read_csv the parameters, but according to the function we are divided into different categories.

Basic parameters

filepath_or_buffer

A data input path, the path may be a file, it may be a URL, or any object to realize a read method. The first argument is that we enter.

In [2]: pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data')
Out[2]:
     5.1  3.5  1.4  0.2     Iris-setosa
0    4.9  3.0  1.4  0.2     Iris-setosa
1    4.7  3.2  1.3  0.2     Iris-setosa
2    4.6  3.1  1.5  0.2     Iris-setosa
3    5.0  3.6  1.4  0.2     Iris-setosa
4    5.4  3.9  1.7  0.4     Iris-setosa
..   ...  ...  ...  ...             ...
144  6.7  3.0  5.2  2.3  Iris-virginica
145  6.3  2.5  5.0  1.9  Iris-virginica
146  6.5  3.0  5.2  2.0  Iris-virginica
147  6.2  3.4  5.4  2.3  Iris-virginica
148  5.9  3.0  5.1  1.8  Iris-virginica

[149 rows x 5 columns]

sep

Delimiter data file, the default is the comma.

Example: The following is a delimiter girl.csv file \t, if the default sep comma delimited, data reading mixed into one.

In [4]: df = pd.read_csv('girl.csv')
In [5]: df
Out[5]:
      name\tage\tgender
0     椎名真白\t18\t女
1     古明地觉\t17\t女
2     古明地恋\t16\t女
# 分隔符指定错误,所以多个列的数据连在一块了

sep must be set '\t', the data will be properly divided.

In [1]: df = pd.read_csv('girl.csv', sep='\t')
In [2]: df
Out[2]:
   name     age     gender
0  椎名真白   18      女
1  古明地觉   17      女
2  古明地恋   16      女

delimiter

Another name separators, similar sep function.

delimiter_whitespace

Added after 0.18 version parameter, the default is False, set to True, it indicates that the delimiter character is blank, can be a space, \tand so on.

As follows girl.csv file separator \t, delim_whitespace set to True:

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

In [5]: df
Out[5]:
   name     age     gender
0  椎名真白   18      女
1  古明地觉   17      女
2  古明地恋   16      女
# 不管分隔符是什么,只要是空白字符,那么可以通过delim_whitespace=True进行读取

header

Set the column name of the import DataFrame, the default is 'infer', pay attention to its delicate relationship with the names of the parameters described below.

names

When not been assigned names, header becomes 0, i.e., the first line of the data file selected as the column name.

When names are assigned header has not been assigned, the header will become None. If you are assigned, it will achieve a combination of functions of the two parameters.

We illustrate

  • names 没有被赋值,header 也没赋值:

    In [1]: df = pd.read_csv('girl.csv', delim_whitespace=True)
    
    In [2]: df
    Out[2]:
       name   age     gender
    0  椎名真白   18      女
    1  古明地觉   17      女
    2  古明地恋   16      女
    # 我们说这种情况下,header为变成0,即选取文件的第一行作为表头
  • names 没有赋值,header 被赋值

    In [1]: df = pd.read_csv('girl.csv', delim_whitespace=True, header=1)
    
    In [2]: df
    Out[2]:
       椎名真白  18  女
    0  古明地觉  17  女
    1  古明地恋  16  女
    # 不指定names,指定header为1,则选取第二行当做表头,第二行下面的是数据
  • names 被赋值,header 没有被赋值

    In [1]: df = pd.read_csv('girl.csv', delim_whitespace=True, names=["姓名", "年龄", "性别"])
    
    In [2]: df
    Out[2]:
         姓名    年龄      性别
    0  name    age    gender
    1  椎名真白   18       女
    2  古明地觉   17       女
    3  古明地恋   16       女    
    # 我们看到names适用于没有表头的情况
    # 指定names没有指定header,那么header相当于None
    # 一般来说,读取文件会有一个表头的,一般是第一行,但是有的文件只是数据而没有表头
    # 那么这个时候我们就可以通过names手动指定、或者生成表头,而文件里面的数据则全部是内容
    # 所以这里那么name、age、gender也当成是一条记录了,本来它是表头的,但是我们指定了names,所以它就变成数据了,表头是我们在names里面指定的
  • names和header都被赋值

    In [1]: df = pd.read_csv('girl.csv', 
                             delim_whitespace=True, 
                             names=["姓名", "年龄", "性别"],
                             header=0)
    
    In [2]: df
    Out[2]:
         姓名  年龄 性别
    0  椎名真白  18  女
    1  古明地觉  17  女
    2  古明地恋  16  女
    # 这个相当于先不看names,只看header,我们说header等于0代表什么呢?显然是把第一行当做表头,下面的当成数据
    # 好了,然后再把表头用names给替换掉
    
    # 再来看个栗子
    In [1]: df = pd.read_csv('girl.csv', 
                             delim_whitespace=True, 
                             names=["姓名", "年龄", "性别"],
                             header=1)
    
    In [2]: df
    Out[2]:
         姓名  年龄 性别
    0  古明地觉  17  女
    1  古明地恋  16  女
    # header=1,表示第二行当做表头,第二行下面当成数据
    # 然后再把表头用names给替换掉,就是上面的结果
    # 所以一般情况下,有表头并且是第一行,那么names和header都无需指定
    # 但是有表头、而表头不是第一行,可能从下面几行开始才是真正的表头和数据,这个是指定header即可
    # 如果没有表头,全部是纯数据,那么我们可以通过names手动生成表头
    # 而names和header都指定的情况下,一般是有表头但是这个表头你不想用,所以用names来把原来的表头替换掉,其实就等价于读取之后再对列名进行rename

index_col

After we read the file, the default generated index is 0123 ... we can certainly set_index, but it can also be specified as an index when read

In [1]: df = pd.read_csv('girl.csv', delim_whitespace=True, index_col="name")

In [2]: df
Out[2]:
      age gender
name            
椎名真白   18      女
古明地觉   17      女
古明地恋   16      女
# 这里指定"name"作为索引,另外除了指定单个列,还可以指定多个列,比如["name", "age"]
# 并且我们可以输入列的名字,也可以输入对应的索引。比如:name, age, gender,它们对应的索引就是0, 1, 2

usecols

If there are many columns, but we do not want all of the columns, but as long as the specified column can use this parameter.

In [1]: df = pd.read_csv('girl.csv', delim_whitespace=True, usecols=["name", "age"])

In [2]: df
Out[2]:
   name  age
0  椎名真白   18
1  古明地觉   17
2  古明地恋   16
# 这里只要name和age两列

mangle_dupe_cols

The actual production data can be complex, the imported data may contain the same name column. Mangle_dupe_cols default parameter is True, the same name of the column after more than an introduction .1. If set to False, throws not supported exception:

# ValueError: Setting mangle_dupe_cols=False is not supported yet

prefix

prefix parameter, when there is no data import header, this parameter is automatically set a prefix. such as:

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

In [2]: df
Out[2]:
      0     1       2
0  name     age     gender
1  椎名真白   18       女
2  古明地觉   17       女
3  古明地恋   16       女
# 我们看到在不指定names的时候,header默认为0,表示以第一行为表头
# 但如果不指定names、还显式地将header指定为None,那么会自动生成表头0 1 2 3...
# 因为DataFrame肯定是要有列名(表头)的

In [1]: df = pd.read_csv('girl.csv', delim_whitespace=True, header=None, prefix="xx")

In [2]: df
Out[2]:
      xx0  xx1     xx2
0  name     age     gender
1  椎名真白   18       女
2  古明地觉   17       女
3  古明地恋   16       女
# 而prefix就是给这样的列名增加前缀的
# 但感觉不是很常用

The general equation parameters

dtype

I once met a rather awkward thing is to deal with the subway personnel data. id staff are beginning to 0, such as 0100012521, which is a string. But when read parsed into an integer, the result is the beginning of the 0 to the lost. This time we will be able to specify the type of a column by dtype, is to tell you to resolve pandas as I type specified at the time of resolution.

In [1]: df = pd.read_csv('girl.csv', delim_whitespace=True, dtype={"age": str})

In [2]: df
Out[2]:
   name age gender
0  椎名真白  18      女
1  古明地觉  17      女
2  古明地恋  16      女
# 这里就表示要把age解析成字符串

engine

When pandas used to parse the data engine, Pandas current analytic engine provides two: C, Python, default is C, because C engine parses faster, but the feature is not full Python engine. If you do not use the features of C engine, the engine will automatically degenerate into Python.

For example, using delimiter parsing, if the specified delimiter is not a single character, or "\s+", then C engine can not be resolved. We know that if delimiter is a blank character, then you can specify delim_whitespace=True, but you can also specify sep = r "\ s +" .

In [1]: df = pd.read_csv('girl.csv', sep=r"\s+")

In [2]: df
Out[2]:
   name age gender
0  椎名真白  18      女
1  古明地觉  17      女
2  古明地恋  16      女
# 如果sep是单个字符,或者字符串\s+,那么C是可以解决的。
# 但如果我们指定的sep比较复杂,这时候引擎就会退化。

# 我们指定的\s{0}相当于没指定,\s+\s{0}在结果上等同于\s+。
# 但是它不是单个字符,也不是\s+,因此此时的C引擎就无法解决了,而是会退化为python引擎
In [1]: df = pd.read_csv('girl.csv', sep=r"\s+\s{0}", encoding="utf-8")

In [2]: df
Out[2]:
ParserWarning: Falling back to the 'python' engine 
    because the 'c' engine does not support regex separators (separators > 1 char and different from '\s+' are interpreted as regex); 
    you can avoid this warning by specifying engine='python'.
    
   name  age gender
0  椎名真白   18      女
1  古明地觉   17      女
2  古明地恋   16      女
# 我们看到虽然自动退化,但是弹出了警告,这个时候需要手动的指定engine="python"来避免警告
# 这里面还用到了encoding参数,这个后面会说,因为引擎一旦退化,在Windows上不指定会读出乱码
# 这里我们看到sep是可以支持正则的,但是说实话sep这个参数都会设置成单个字符
# 基本上在生成文件的时候,分隔符不会复杂到读取的时候需要使用正则来分隔的。

converters

May transform the column data when read

In [1]: df = pd.read_csv('girl.csv', sep="\t", converters={"age": lambda x: int(x) + 10})

In [2]: df
Out[2]:
   name  age gender
0  椎名真白   28      女
1  古明地觉   27      女
2  古明地恋   26      女    

看到少女们都长了10岁,完成对 age 列的数据加 10,注意 int(x),此处解析器默认所有列的类型为 str,所以需要显式类型转换。

true_values和false_value

指定哪些值应该被清洗为True,哪些值被清洗为False。这两位老铁需要成对出现,只出现一个没有效果。但是说实话,这个不常用

In [1]: df = pd.read_csv('girl.csv', sep="\t")

In [2]: df
Out[2]:
   name     age   gender 对错
0  椎名真白   18      女  对
1  古明地觉   17      女  错
2  古明地恋   16      女  对    
# 加了一个字段

In [1]: df = pd.read_csv('girl.csv', sep="\t", true_values=["对"], false_values=["错"])

In [2]: df
Out[2]:
   name     age   gender  对错
0  椎名真白   18      女   True
1  古明地觉   17      女  False
2  古明地恋   16      女   True    

skiprows

skiprows 过滤行,想过滤掉哪些行,就写在一个列表里面传递给skiprows即可。注意的是:这里是先过滤,然后再确定表头,比如:

In [1]: df = pd.read_csv('girl.csv', sep="\t", skiprows=[0])

In [2]: df
Out[2]:
   椎名真白  18  女  对
0  古明地觉  17  女  错
1  古明地恋  16  女  对
# 我们把第一行过滤掉了,但是第一行是表头
# 所以过滤掉之后,第二行就变成表头了

# 这里过滤第二行
In [1]: df = pd.read_csv('girl.csv', sep="\t", skiprows=[1])

In [2]: df
Out[2]:
   name     age   gender 对错
0  古明地觉   17      女  错
1  古明地恋   16      女  对    

里面除了传入具体的数值,来表明要过滤掉哪一行,还可以传入一个函数

In [1]: df = pd.read_csv('girl.csv', sep="\t", skiprows=lambda x: x > 0 and x % 2 == 0)

In [2]: df
Out[2]:
   name     age   gender 对错
0  椎名真白   18      女  对
1  古明地恋   16      女  对  
# 由于索引从0开始,凡是索引大于0、并且%2等于0的记录都过滤掉
# 索引大于0,是为了保证表头不被过滤掉 

skipfooter

从文件末尾过滤行,解析引擎退化为 Python。这是因为 C 解析引擎没有这个特性。

In [1]: df = pd.read_csv('girl.csv', sep="\t", skipfooter=1, encoding="utf-8", engine="python")

In [2]: df
Out[2]:
   name     age   gender 对错
0  椎名真白   18      女  对
1  古明地觉   17      女  错   
# skipfooter接收整型,表示从结尾往上过滤掉指定数量的行
# 因为引擎退化为python,那么要手动指定engine="python",不然会警告
# 另外需要指定encoding="utf-8",因为csv存在编码问题,当引擎退化为python的时候,在Windows上读取会乱码

nrows

nrows 参数设置一次性读入的文件行数,它在读入大文件时很有用,比如 16G 内存的PC无法容纳几百 G 的大文件。

low_memory

这个看起来是和内存有关的,但其实它是和数据类型相关的。在解释这个原因之前,我们还要先从DataFrame的数据类型说起。

我们知道得到DataFrame的每一列都是有类型的,那么在读取csv的时候,pandas也是要根据数据来判断每一列的类型的。但pandas主要是靠"猜"的方法,因为在读取csv的时候是分块读取的,每读取一块的时候,会根据数据来判断每一列是什么类型;然后再读取下一块,会再对类型进行一个判断,得到每一列的类型,如果得到的结果和上一个块得到结果不一样,那么就会发出警告,提示有以下的列存在多种数据类型:

DtypeWarning: Columns (1,5,8,......) have mixed types. Specify dtype option on import or set low_memory=False.

而为了保证正常读取,那么会把类型像大的方向兼容,比如第一个块的user_id解释成整型,但是第二个块发现user_id有的值无法解析成整型的,那么类型整体就会变成字符串,于是pandas提示该列存在混合类型。而一旦设置low_memory=False,那么pandas在读取csv的时候就不分块读了,而是直接将文件全部读取到内存里面,这样只需要对整体进行一次判断,就能得到每一列的类型。但是这种方式也有缺陷,一旦csv过大,就会内存溢出。

但是从数据库读取就不用担心了,因为数据库是规定了每一列的类型的。如果是从数据库读取得到的DataFrame,那么每一列的数据类型和数据库表中的类型是一致的。

还有,我们在上面介绍了dtype,这个是我们手动规定类型。那么pandas就会按照我们规定的类型去解析指定的列,但是一旦无法解析就会报错。

memory_map

如果你知道python的一个模块mmap,那么你肯定很好理解。如果使用的读取在内存里,那么直接进行映射即可,不会再次进行IO操作。默认为False

空值处理相关参数

na_values

na_values 参数可以配置哪些值需要处理成 NaN,这个是非常常用的,但是用的人不多。

df = pd.read_csv('girl.csv')
print(df)
"""
      name  age gender
0  mashiro   18      女
1        #   17      女
2   koishi   16      #
"""

# 将#全部换成NaN
df = pd.read_csv('girl.csv', na_values=["#"])
print(df)
"""
      name  age gender
0  mashiro   18      女
1      NaN   17      女
2   koishi   16    NaN
"""

# 也可以指定多个值
df = pd.read_csv('girl.csv', na_values=["#", "mashiro"])
print(df)
"""
     name  age gender
0     NaN   18      女
1     NaN   17      女
2  koishi   16    NaN
"""

# 也可以只对指定的列进行替换
df = pd.read_csv('girl.csv', na_values={"name": ["#"], "gender": ["女"]})
print(df)
"""
      name  age gender
0  mashiro   18    NaN
1      NaN   17    NaN
2   koishi   16      #
"""

keep_default_na 是和 na_values 搭配的,如果前者为 True,则 na_values 被解析为 Na/NaN 的字符除了用户设置外,还包括默认值。默认为True

skip_blank_lines

skip_blank_lines 默认为 True,则过滤掉空行,如为 False 则解析为 NaN

verbose

打印一些重要信息

时间处理相关参数

parse_dates

指定某些列为时间类型。

df = pd.read_csv("xx.csv", parse_dates=["column"])

date_parser

date_parser 参数定制某种时间类型,详细使用过程总结如下。因为有些格式虽然是日期,但不是那种可以直接转换的样子:比如'2018-01-01'。可能是这种类型:'2018年1月1日',这个时候我们就需要手动来定制解析的规则

df = pd.read_csv("xx.csv", parse_dates=["column"], date_parser=lambda x: pd.datetime.strptime(x, "%Y年%m月%d日"))

infer_datetime_format

infer_datetime_format 参数默认为 False。如果设定为 True 并且 parse_dates 可用,那么 Pandas 将尝试转换为日期类型,如果可以转换,转换方法并解析,在某些情况下会快 5~10 倍。

分块读入相关参数

分块读入内存,尤其单机处理大文件时会很有用。

iterator

iterator 取值 boolean,默认为False。如果为True,那么返回一个 TextFileReader 对象,以便逐块处理文件。这个在文件很大时,内存无法容纳所有数据文件,此时分批读入,依次处理。

# 此时返回一个类似于迭代器的对象
chunk = pd.read_csv('girl.csv', iterator=True)
# 调用get_chunk,里面传入整型,来读取指定的行数
print(chunk.get_chunk(1))
"""
      name  age gender
0  mashiro   18      女
"""
print(chunk.get_chunk(2))
"""
     name  age gender
1       #   17      女
2  koishi   16      #
"""
try:
    print(chunk.get_chunk(2))
except StopIteration:
    print("文件读取完毕")  # 文件读取完毕

# 文件总共三行,所以读完之后,再读就溢出了
# 如果还剩下1行,但是我们指定读取100,那么也不会报错
# 不够指定的行数,那么有多少返回多少

chunksize

chunksize 整型,默认为 None,设置文件块的大小。

chunk = pd.read_csv('girl.csv', chunksize=2)
# 还是返回一个类似于迭代器的对象
print(chunk)  # <pandas.io.parsers.TextFileReader object at 0x00000258C41B2CD0>

# 调用get_chunk,如果不指定行数,那么就是默认的chunksize
print(chunk.get_chunk())
"""
      name  age gender
0  mashiro   18      女
1        #   17      女
"""
# 但也可以指定
print(chunk.get_chunk(1))
"""
     name  age gender
2  koishi   16      #
"""
try:
    print(chunk.get_chunk(2))
except StopIteration:
    print("文件读取完毕")  # 文件读取完毕

格式和压缩相关参数

compression

compression 参数取值为 {‘infer’, ‘gzip’, ‘bz2’, ‘zip’, ‘xz’, None},默认 ‘infer’,直接使用磁盘上的压缩文件。

如果使用 infer 参数,则使用 gzip、bz2、zip 或者解压文件名中以 ‘.gz’、‘.bz2’、‘.zip’ 或 ‘xz’ 这些为后缀的文件,否则不解压。

如果使用 zip,那么 ZIP 包中必须只包含一个文件。设置为 None 则不解压。

# 直接将上面的girl.csv添加到压缩文件,打包成girl.zip
df = pd.read_csv('girl.zip', compression="zip")
print(df)
"""
      name  age gender
0  mashiro   18      女
1        #   17      女
2   koishi   16      #
"""
# 会自动解包,读取文件,但是如果没有compression参数,那么就会报错了
# UnicodeDecodeError: 'utf-8' codec can't decode byte 0xce in position 0: invalid continuation byte

thousands

千分位分割符,如 , 或者 .,默认为None

encoding

encoding 指定字符集类型,通常指定为 'utf-8'。根据情况也可能是ISO-8859-1

error_bad_lines和warn_bad_lines

如果一行包含过多的列,假设csv的数据有3列,但是某一行却有4个数据,显然数据有问题。那么默认情况下不会返回DataFrame,而是会报错。

# pandas.errors.ParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 4

我们在某一行中多加了一个数据,结果显示错误。因为girl.csv里面有三列,但是有一行却有四个数据,所以报错。

在小样本读取时,这个错误很快就能发现。但是如果样本比较大、并且由于数据集不可能那么干净、很容易出现这种情况,那么该怎么办呢?而且这种情况下,Excel基本上是打不开这么大的文件的。这个时候我们就可以将error_bad_lines设置为False(默认为True),意思是遇到这种情况,直接把这一行给我扔掉。同时会设置 warn_bad_lines 设置为True,打印剔除的这行。

df = pd.read_csv('girl.csv', error_bad_lines=False, warn_bad_lines=True)
print(df)
"""
      name  age gender
0  mashiro   18      女
1   koishi   16      #

b'Skipping line 3: expected 3 fields, saw 4\n'
"""

以上两参数只能在C解析引擎下使用。

总结

pandas在读取csv的时候支持的参数是很多的,其中部分参数也适用于读取其它类型的文件。这些参数虽然很多平常都不会用,但是还是要了解,因为read_csv的其它参数是可以很方便地解决某些问题的。

Guess you like

Origin www.cnblogs.com/traditional/p/12514914.html