导读:pandas.read_csv接口用于读取CSV格式的数据文件,由于CSV文件使用非常频繁,功能强大,参数众多,因此在这里专门做详细介绍。
作者:李庆辉
来源:大数据DT(ID:hzdashuju)
01 语法
基本语法如下,pd为导入Pandas模块的别名:
pd.read_csv(filepath_or_buffer: Union[str, pathlib.Path, IO[~AnyStr]],

            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
,

            cache_dates=
True
, iterator=
False
, chunksize=
None
,

            compression=
'infer'
, thousands=
None
, decimal: str = 
'.'
,

            lineterminator=
None
, quotechar=
'"'
, quoting=
0
,

            doublequote=
True
, escapechar=
None
, comment=
None
,

            encoding=
None
, dialect=
None
, error_bad_lines=
True
,

            warn_bad_lines=
True
, delim_whitespace=
False
,

            low_memory=
True
, memory_map=
False
, float_precision=
None
)
一般情况下,会将读取到的数据返回一个DataFrame,当然按照参数的要求会返回指定的类型。
02 数据内容
filepath_or_buffer为第一个参数,没有默认值,也不能为空,根据Python的语法,第一个参数传参时可以不写参数名。可以传文件路径:
# 支持文件路径或者文件缓冲对象
# 本地相对路径
pd.read_csv(
'data/data.csv'
# 注意目录层级
pd.read_csv(
'data.csv'
# 如果文件与代码文件在同一目录下
pd.read_csv(
'data/my/my.data'
# CSV文件的扩展名不一定是.csv
# 本地绝对路径
pd.read_csv(
'/user/gairuo/data/data.csv'
)

# 使用URL
pd.read_csv(
'https://www.gairuo.com/file/data/dataset/GDP-China.csv'
)
需要注意的是,Mac中和Windows中路径的写法不一样,上例是Mac中的写法,Windows中的相对路径和绝对路径需要分别换成类似'data\data.csv'和'E: \data\data.csv'的形式。另外,路径尽量不要使用中文,否则程序容易报错,这意味着你存放数据文件的目录要尽量用英文命名。
可以传数据字符串,即CSV中的数据字符以字符串形式直接传入:
from
 io 
import
 StringIO

data = (
'col1,col2,col3\n'
'a,b,1\n'
'a,b,2\n'
'c,d,3'
)


pd.read_csv(StringIO(data))

pd.read_csv(StringIO(data), dtype=object)
也可以传入字节数据:
from
 io 
import
 BytesIO

data = (
b'word,length\n'
b'Tr\xc3\xa4umen,7\n'
b'Gr\xc3\xbc\xc3\x9fe,5'
)


pd.read_csv(BytesIO(data))
03 分隔符
sep参数是字符型的,代表每行数据内容的分隔符号,默认是逗号,另外常见的还有制表符(\t)、空格等,根据数据的实际情况传值。
# 数据分隔符默认是逗号,可以指定为其他符号
pd.read_csv(data, sep=
'\t'
# 制表符分隔tab
pd.read_table(data) 
# read_table 默认是制表符分隔tab
pd.read_csv(data, sep=
'|'
# 制表符分隔tab
pd.read_csv(data,sep=
"(?<!a)\|(?!1)"
, engine=
'python'
# 使用正则表达式
pd.read_csv还提供了一个参数名为delimiter的定界符,这是一个备选分隔符,是sep的别名,效果和sep一样。如果指定该参数,则sep参数失效。
04 表头
header参数支持整型和由整型组成的列表,指定第几行是表头,默认会自动推断把第一行作为表头。
pd.read_csv(data, header=
0
# 第一行
pd.read_csv(data, header=
None
# 没有表头
pd.read_csv(data, header=[
0
,
1
,
3
]) 
# 多层索引MultiIndex
  • 注意:如果skip_blank_lines=True,header参数将忽略空行和注释行, 因此header=0表示第一行数据而非文件的第一行。
05 列名
names用来指定列的名称,它是一个类似列表的序列,与数据一一对应。如果文件不包含列名,那么应该设置header=None,列名列表中不允许有重复值。
pd.read_csv(data, names=[
'列1'
'列2'
]) 
# 指定列名列表
pd.read_csv(data, names=[
'列1'
'列2'
], header=
None
)
06 索引
index_col用来指定索引列,可以是行索引的列编号或者列名,如果给定一个序列,则有多个行索引。Pandas不会自动将第一列作为索引,不指定时会自动使用以0开始的自然索引。
# 支持int、str、int序列、str序列、False,默认为None
pd.read_csv(data, index_col=
False
# 不再使用首列作为索引
pd.read_csv(data, index_col=
0
# 第几列是索引
pd.read_csv(data, index_col=
'年份'
# 指定列名
pd.read_csv(data, index_col=[
'a'
,
'b'
]) 
# 多个索引
pd.read_csv(data, index_col=[
0
3
]) 
# 按列索引指定多个索引
07 使用部分列
如果只使用数据的部分列,可以用usecols来指定,这样可以加快加载速度并降低内存消耗。
# 支持类似列表的序列和可调用对象
# 读取部分列
pd.read_csv(data, usecols=[
0
,
4
,
3
]) 
# 按索引只读取指定列,与顺序无关
pd.read_csv(data, usecols=[
'列1'
'列5'
]) 
# 按列名,列名必须存在
# 指定列顺序,其实是df的筛选功能
pd.read_csv(data, usecols=[
'列1'
'列5'
])[[
'列5'
'列1'
]]

# 以下用callable方式可以巧妙指定顺序,in后面的是我们要的顺序
pd.read_csv(data, usecols=
lambda
 x: x.upper() 
in
 [
'COL3'
'COL1'
])
08 返回序列
将squeeze设置为True,如果文件只包含一列,则返回一个Series,如果有多列,则还是返回DataFrame。
# 布尔型,默认为False
# 下例只取一列,会返回一个Series
pd.read_csv(data, usecols=[
0
], squeeze=
True
)

# 有两列则还是df
pd.read_csv(data, usecols=[
0
2
], squeeze=
True
)
09 表头前缀
如果原始数据没有列名,可以指定一个前缀加序数的名称,如n0、n1,通过prefix参数指定前缀。
# 格式为字符型str
# 表头为c_0、c_2
pd.read_csv(data, prefix='c_', header=None)
10 处理重复列名
如果该参数为True,当列名有重复时,解析列名将变为X, X.1, …, X.N,而不是X, …, X。如果该参数为False,那么当列名中有重复时,前列将会被后列覆盖。
# 布尔型,默认为True
data = 
'a,b,a\n0,1,2\n3,4,5'
pd.read_csv(StringIO(data), mangle_dupe_cols=
True
)

# 表头为a b a.1
# False会报ValueError错误
11 数据类型
dtype可以指定各数据列的数据类型。
# 传入类型名称,或者以列名为键、以指定类型为值的字典
pd.read_csv(data, dtype=np.float64) 
# 所有数据均为此数据类型
pd.read_csv(data, dtype={
'c1'
:np.float64, 
'c2'
: str}) 
# 指定字段的类型
pd.read_csv(data, dtype=[datetime, datetime, str, float]) 
# 依次指定
12 引擎
使用的分析引擎可以选择C或Python。C语言的速度最快,Python语言的功能最为完善,一般情况下,不需要另行指定。
# 格式为engine=None,其中可选值有{'c', 'python'}
pd.read_csv(data, engine='c')
13 列数据处理
使用converters参数对列的数据进行转换,参数中指定列名与针对此列的处理函数,最终以字典的形式传入,字典的键可以是列名或者列的序号。
# 字典格式,默认为None
data = 
'x,y\na,1\nb,2'
deffoo(p):
return
 p+
's'
# x应用函数,y使用lambda
pd.read_csv(StringIO(data), converters={
'x'
: foo,

'y'
lambda
 x: x*
3
})

# 使用列索引
pd.read_csv(StringIO(data),

            converters={
0
: foo, 
1
lambda
 x: x*
3
})

14 真假值转换
使用true_values和false_values将指定的文本内容转换为True或False,可以用列表指定多个值。
# 列表,默认为None
data = (
'a,b,c\n1,Yes,2\n3,No,4'
)

pd.read_csv(StringIO(data),

            true_values=[
'Yes'
], false_values=[
'No'
])

15 跳过指定行
如下跳过需要忽略的行数(从文件开始处算起)或需要忽略的行号列表(从0开始):
# 类似列表的序列或者可调用对象
# 跳过前三行
pd.read_csv(data, skiprows=
2
)

# 跳过前三行
pd.read_csv(data, skiprows=range(
2
))

# 跳过指定行
pd.read_csv(data, skiprows=[
24
,
234
,
141
])

# 跳过指定行
pd.read_csv(data, skiprows=np.array([
2
6
11
]))

# 隔行跳过
pd.read_csv(data, skiprows=
lambda
 x: x % 
2
 != 
0
)

尾部跳过,从文件尾部开始忽略,C引擎不支持。
# int类型, 默认为0
pd.read_csv(filename, skipfooter=
1
# 最后一行不加载
skip_blank_lines指定是否跳过空行,如果为True,则跳过空行,否则数据记为NaN。
# 布尔型,默认为True
# 不跳过空行
pd.read_csv(data, skip_blank_lines=
False
)

如果skip_blank_lines=True,header参数将忽略空行和注释行, 因此header=0表示第一行数据而非文件的第一行。
16 读取指定行
nrows参数用于指定需要读取的行数,从文件第一行算起,经常用于较大的数据,先取部分进行代码编写。
# int类型,默认为None
pd.read_csv(data, nrows=
1000
)

17 空值替换
na_values参数的值是一组用于替换NA/NaN的值。如果传参,需要指定特定列的空值。以下值默认会被认定为空值:
[
'-1.#IND'
'1.#QNAN'
'1.#IND'
'-1.#QNAN'
,

'#N/A N/A'
'#N/A'
'N/A'
'n/a'
'NA'
,

'#NA'
'NULL'
'null'
'NaN'
'-NaN'
,

'nan'
'-nan'
''
]

使用na_values时需要关注下面keep_default_na的配合使用和影响:
# 可传入标量、字符串、类似列表序列和字典,默认为None
# 5和5.0会被认为是NaN
pd.read_csv(data, na_values=[
5
])

# ?会被认为是NaN
pd.read_csv(data, na_values=
'?'
)

# 空值为NaN
pd.read_csv(data, keep_default_na=
False
, na_values=[
""
])

# 字符NA和字符0会被认为是NaN
pd.read_csv(data, keep_default_na=
False
, na_values=[
"NA"
"0"
])

# Nope会被认为是NaN
pd.read_csv(data, na_values=[
"Nope"
])

# a、b、c均被认为是NaN,等于na_values=['a','b','c']
pd.read_csv(data, na_values=
'abc'
)

# 指定列的指定值会被认为是NaN
pd.read_csv(data, na_values={
'c'
:
3
1
:[
2
,
5
]})

18 保留默认空值
分析数据时是否包含默认的NaN值,是否自动识别。如果指定na_values参数,并且 keep_default_na=False,那么默认的NaN将被覆盖,否则添加。keep_default_na和na_values的关系见表3-2。
▼表3-2 keep_default_na和na_values的取值逻辑关系
  • 说明:如果na_filter为False(默认为True),那么keep_default_na和na_values参数均无效。
# 布尔型,默认为True
# 不自动识别空值
pd.read_csv(data, keep_default_na=
False
)

na_filter为是否检查丢失值(空字符串或空值)。对于大文件来说,数据集中没有空值,设定na_filter=False可以提升读取速度。
# 布尔型,默认为True
pd.read_csv(data, na_filter=
False
# 不检查
19 日期时间解析
日期时间解析器参数date_parser用于解析日期的函数,默认使用dateutil.parser.parser来做转换。
如果为某些或所有列启用了parse_dates,并且datetime字符串的格式都相同,则通过设置infer_datetime_format=True,可以大大提高解析速度,pandas将尝试推断datetime字符串的格式,然后使用更快的方法解析字符串,从而将解析速度提高5~10倍。如果无法对整列做出正确的推断解析,Pandas将返回到正常的解析模式。
下面是一些可自动推断的日期时间字符串示例,它们都表示2020年12月30日00:00:00:
  • "20201230"
  • "2020/12/30"
  • "20201230 00:00:00"
  • "12/30/2020 00:00:00"
  • "30/Dec/2020 00:00:00"
  • "30/December/2020 00:00:00"
# 解析时间的函数名,默认为None
# 指定时间解析库,默认是dateutil.parser.parser
date_parser = pd.io.date_converters.parse_date_time

date_parser = 
lambda
 x: pd.to_datetime(x, utc=
True
, format=
'%d%b%Y'
)

date_parser = 
lambda
 d: pd.datetime.strptime(d, 
'%d%b%Y'
)

# 使用
pd.read_csv(data, parse_dates=[
'年份'
], date_parser=date_parser)

parse_dates参数用于对时间日期进行解析。
# 布尔型、整型组成的列表、列表组成的列表或者字典,默认为False
pd.read_csv(data, parse_dates=
True
# 自动解析日期时间格式
pd.read_csv(data, parse_dates=[
'年份'
]) 
# 指定日期时间字段进行解析
# 将第1、4列合并解析成名为“时间”的时间类型列
pd.read_csv(data, parse_dates={
'时间'
:[
1
,
4
]})

如果infer_datetime_format被设定为True并且parse_dates可用,那么Pandas将尝试转换为日期类型。
# 布尔型,默认为False
pd.read_csv(data, parse_dates=
True
, infer_datetime_format=
True
)

如果用上文中的parse_dates参数将多列合并并解析成一个时间列,设置keep_date_col的值为True时,会保留这些原有的时间组成列;如果设置为False,则不保留这些列。
# 布尔型,默认为False
pd.read_csv(data, parse_dates=[[
1
2
], [
1
3
]], keep_date_col=
True
)

对于DD/MM格式的日期类型,如日期2020-01-06,如果dayfirst=True,则会转换成2020-06-01。
# 布尔型,默认为False
pd.read_csv(data, dayfirst=
True
, parse_dates=[
0
])

cache_dates如果为True,则使用唯一的转换日期缓存来应用datetime转换。解析重复的日期字符串,尤其是带有时区偏移的日期字符串时,可能会大大提高速度。
# 布尔型,默认为True
pd.read_csv(data, cache_dates=
False
)

20 文件处理
以下是一些对读取文件对象的处理方法。iterator参数如果设置为True,则返回一个TextFileReader对象,并可以对它进行迭代,以便逐块处理文件。
# 布尔型,默认为False
pd.read_csv(data, iterator=
True
)

chunksize指定文件块的大小,分块处理大型CSV文件。
# 整型,默认为None
pd.read_csv(data, chunksize=
100000
)


# 分块处理大文件
df_iterator = pd.read_csv(file, chunksize=
50000
)

defprocess_dataframe(df):
pass
return
 processed_df


for
 index,df_tmp 
in
 enumerate(df_iterator):

    df_processed = process_dataframe(df_tmp)

if
 index > 
0
:

       df_processed.to_csv(path)

else
:

       df_processed.to_csv(path, mode=
'a'
, header=
False
)

compression(压缩格式)用于对磁盘数据进行即时解压缩。如果为“infer”,且filepath_or_buffer是以.gz、.bz2、.zip或.xz结尾的字符串,则使用gzip、bz2、zip或xz,否则不进行解压缩。如果使用zip,则ZIP文件必须仅包含一个要读取的数据文件。设置为None将不进行解压缩。
# 可选值有'infer'、'gzip'、'bz2'、'zip'、'xz'和None,默认为'infer'
pd.read_csv(
'sample.tar.gz'
, compression=
'gzip'
)

encoding(编码)指定字符集类型,通常指定为'utf-8'。
# 字符型,默认为None
pd.read_csv(
'gairuo.csv'
, encoding=
'utf8'
)

pd.read_csv(
"gairuo.csv"
,encoding=
"gb2312"
# 常见中文
21 符号
以下是对文件中的一些数据符号进行的特殊识别处理。如下设置千分位分隔符thousands:
# 字符型,默认为None
pd.read_csv(
'test.csv'
, thousands=
','
# 逗号分隔
小数点decimal,识别为小数点的字符。
# 字符串,默认为'.'
pd.read_csv(data, decimal=
","
)

行结束符lineterminator,将文件分成几行的字符,仅对C解析器有效。
# 长度为1的字符串,默认为None
data = 
'a,b,c~1,2,3~4,5,6'
pd.read_csv(StringIO(data), lineterminator=
'~'
)

引号quotechar,用于表示引用数据的开始和结束的字符。引用的项目可以包含定界符,它将被忽略。
# 长度为1的字符串
pd.read_csv(file, quotechar=
'"'
)

在csv模块中,数据可能会用引号等字符包裹起来,quoting参数用来控制识别字段的引号模式,它可以是Python csv模块中的csv.QUOTE_*常量,也可以传入对应的数字。各个传入值的意义如下。
  • 0或csv.QUOTE_MINIMAL:仅特殊字段有引号。
  • 1或csv.QUOTE_ALL:所有字段都有引号。
  • 2或csv.QUOTE_NONNUMERIC:所有非数字字段都有引号。
  • 3或csv.QUOTE_NONE:所有字段都没有引号。
如果使用csv模块,则需要事先引入csv模块。
# 整型或者csv.QUOTE_*实例, 默认为0
import
 csv

pd.read_csv(
'input_file.csv'
, quoting=csv.QUOTE_NONE)

双引号doublequote,当单引号已经被定义,并且quoting参数不是QUOTE_NONE的时候,使用双引号表示将引号内的元素作为一个元素使用。
# 布尔型,默认为True
import
 csv

pd.read_csv(
'data.csv'
, quotechar=
'"'
, doublequote=
True
, quoting=csv.QUOTE_NONNUMERIC)

escapechar可以传入一个转义符,用于过滤数据中的该转入符。比如,如果一行用双引号包裹着的数据中有换行符,用以下代码可以过滤其中的换行符。
# 长度为1的转义字符串,默认为None
pd.read_csv(StringIO(data), escapechar=
'\n'
, encoding=
'utf-8'
)

注释标识comment,指示不应分析行的部分。如果在一行的开头找到该标识,则将完全忽略该行。此参数必须是单个字符。像空行一样(只要skip_blank_lines = True),注释的行将被参数header忽略,而不是被skiprows忽略。例如,如果comment ='#',则解析header=0的'#empty \ na,b,c \ n1,2,3'会将'a,b,c'视为header。
# 字符串,默认为None
s = 
'# notes\na,b,c\n# more notes\n1,2,3'
pd.read_csv(StringIO(s), sep=
','
, comment=
'#'
, skiprows=
1
)

空格分隔符delim_whitespace,指定是否将空格(例如''或'\ t')用作分隔符,等效于设置sep ='\s+'。如果此选项设置为True,则不应该为delimiter参数传递任何内容。
# 布尔型,默认为False
pd.read_csv(StringIO(data), delim_whitespace=
False
)

22 小结
通过本文的介绍,我们了解了读取CSV文件的一些参数的功能,也了解了在读取CSV文件时可以做一些初步的数据整理工作。
关于作者:李庆辉,数据产品专家,某电商公司数据产品团队负责人,擅长通过数据治理、数据分析、数据化运营提升公司的数据应用水平。精通Python数据科学及Python Web开发,曾独立开发公司的自动化数据分析平台,参与教育部“1+X”数据分析(Python)职业技能等级标准评审。中国人工智能学会会员,企业数字化、数据产品和数据分析讲师,在个人网站“盖若”上编写的技术和产品教程广受欢迎。
本书摘编自《深入浅出Pandas:利用Python进行数据处理与分析》,机械工业出版社华章公司2021年出版。转载请与我们取得授权。
延伸阅读深入浅出Pandas
点击上图了解及购买

转载请联系微信:DoctorData
推荐语:这是一本全面覆盖了Pandas使用者的普遍需求和痛点的著作,基于实用、易学的原则,从功能、使用、原理等多个维度对Pandas做了全方位的详细讲解,既是初学者系统学习Pandas难得的入门书,又是有经验的Python工程师案头必不可少的查询手册。《利用Python进行数据分析》学习伴侣,用好Python必备。
划重点👇
更多精彩👇
在公众号对话框输入以下关键词
查看更多优质内容!
PPT | 读书 | 书单 | 硬核 | 干货|讲明白|神操作
大数据 | 云计算 | 数据库 | Python | 爬虫 | 可视化
AI | 人工智能 | 机器学习 | 深度学习 | NLP
5G|中台 | 用户画像1024 | 数学 | 算法 数字孪生
据统计,99%的大咖都关注了这个公众号
👇
继续阅读
阅读原文