用Pandas读取CSV,看这篇就够了

时间:2022-11-25 17:28:37

 用Pandas读取CSV,看这篇就够了

01 语法

基本语法如下,pd为导入Pandas模块的别名:

  1. pd.read_csv(filepath_or_buffer: Union[str, pathlib.Path, IO[~AnyStr]],  
  2.             sep=','delimiter=Noneheader='infer'names=Noneindex_col=None 
  3.             usecols=Nonesqueeze=Falseprefix=Nonemangle_dupe_cols=True 
  4.             dtype=Noneengine=Noneconverters=Nonetrue_values=None 
  5.             false_values=Noneskipinitialspace=Falseskiprows=None 
  6.             skipfooter=0nrows=Nonena_values=Nonekeep_default_na=True 
  7.             na_filter=Trueverbose=Falseskip_blank_lines=True 
  8.             parse_dates=Falseinfer_datetime_format=False 
  9.             keep_date_col=Falsedate_parser=Nonedayfirst=False 
  10.             cache_dates=Trueiterator=Falsechunksize=None 
  11.             compression='infer'thousands=None, decimal: str = '.' 
  12.             lineterminator=Nonequotechar='"'quoting=0 
  13.             doublequote=Trueescapechar=Nonecomment=None 
  14.             encoding=Nonedialect=Noneerror_bad_lines=True 
  15.             warn_bad_lines=Truedelim_whitespace=False 
  16.             low_memory=Truememory_map=Falsefloat_precision=None

一般情况下,会将读取到的数据返回一个DataFrame,当然按照参数的要求会返回指定的类型。

02 数据内容

filepath_or_buffer为第一个参数,没有默认值,也不能为空,根据Python的语法,第一个参数传参时可以不写参数名。可以传文件路径:

  1. # 支持文件路径或者文件缓冲对象  
  2. # 本地相对路径  
  3. pd.read_csv('data/data.csv') # 注意目录层级  
  4. pd.read_csv('data.csv') # 如果文件与代码文件在同一目录下  
  5. pd.read_csv('data/my/my.data') # CSV文件的扩展名不一定是.csv  
  6. # 本地绝对路径  
  7. pd.read_csv('/user/gairuo/data/data.csv')  
  8. # 使用URL  
  9. 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中的数据字符以字符串形式直接传入:

  1. from io import StringIO  
  2. data = ('col1,col2,col3\n'  
  3.         'a,b,1\n'  
  4.         'a,b,2\n'  
  5.         'c,d,3')  
  6. pd.read_csv(StringIO(data))  
  7. pd.read_csv(StringIO(data), dtype=object

也可以传入字节数据:

  1. from io import BytesIO  
  2. data = (b'word,length\n'  
  3.         b'Tr\xc3\xa4umen,7\n'  
  4.         b'Gr\xc3\xbc\xc3\x9fe,5')  
  5. pd.read_csv(BytesIO(data)) 

03 分隔符

sep参数是字符型的,代表每行数据内容的分隔符号,默认是逗号,另外常见的还有制表符(\t)、空格等,根据数据的实际情况传值。

  1. # 数据分隔符默认是逗号,可以指定为其他符号  
  2. pd.read_csv(data, sep='\t') # 制表符分隔tab  
  3. pd.read_table(data) # read_table 默认是制表符分隔tab  
  4. pd.read_csv(data, sep='|') # 制表符分隔tab  
  5. pd.read_csv(data,sep="(?<!a)\|(?!1)"engine='python') # 使用正则表达式 

pd.read_csv还提供了一个参数名为delimiter的定界符,这是一个备选分隔符,是sep的别名,效果和sep一样。如果指定该参数,则sep参数失效。

04 表头

header参数支持整型和由整型组成的列表,指定第几行是表头,默认会自动推断把第一行作为表头。

  1. pd.read_csv(data, header=0) # 第一行  
  2. pd.read_csv(data, header=None) # 没有表头  
  3. pd.read_csv(data, header=[0,1,3]) # 多层索引MultiIndex 
  •  注意:如果skip_blank_lines=True,header参数将忽略空行和注释行, 因此header=0表示第一行数据而非文件的第一行。

05 列名

names用来指定列的名称,它是一个类似列表的序列,与数据一一对应。如果文件不包含列名,那么应该设置header=None,列名列表中不允许有重复值。

  1. pd.read_csv(data, names=['列1', '列2']) # 指定列名列表  
  2. pd.read_csv(data, names=['列1', '列2'], header=None

06 索引

index_col用来指定索引列,可以是行索引的列编号或者列名,如果给定一个序列,则有多个行索引。Pandas不会自动将第一列作为索引,不指定时会自动使用以0开始的自然索引。

  1. # 支持int、str、int序列、str序列、False,默认为None  
  2. pd.read_csv(data, index_col=False) # 不再使用首列作为索引  
  3. pd.read_csv(data, index_col=0) # 第几列是索引  
  4. pd.read_csv(data, index_col='年份') # 指定列名  
  5. pd.read_csv(data, index_col=['a','b']) # 多个索引  
  6. pd.read_csv(data, index_col=[0, 3]) # 按列索引指定多个索引 

07 使用部分列

如果只使用数据的部分列,可以用usecols来指定,这样可以加快加载速度并降低内存消耗。

  1. # 支持类似列表的序列和可调用对象  
  2. # 读取部分列  
  3. pd.read_csv(data, usecols=[0,4,3]) # 按索引只读取指定列,与顺序无关  
  4. pd.read_csv(data, usecols=['列1', '列5']) # 按列名,列名必须存在  
  5. # 指定列顺序,其实是df的筛选功能  
  6. pd.read_csv(data, usecols=['列1', '列5'])[['列5', '列1']]  
  7. # 以下用callable方式可以巧妙指定顺序,in后面的是我们要的顺序  
  8. pd.read_csv(data, usecols=lambda x: x.upper() in ['COL3', 'COL1']) 

08 返回序列

将squeeze设置为True,如果文件只包含一列,则返回一个Series,如果有多列,则还是返回DataFrame。

  1. # 布尔型,默认为False  
  2. # 下例只取一列,会返回一个Series  
  3. pd.read_csv(data, usecols=[0], squeeze=True 
  4. # 有两列则还是df  
  5. pd.read_csv(data, usecols=[0, 2], squeeze=True

09 表头前缀

如果原始数据没有列名,可以指定一个前缀加序数的名称,如n0、n1,通过prefix参数指定前缀。

  1. # 格式为字符型str  
  2. # 表头为c_0、c_2  
  3. pd.read_csv(data, prefix='c_'header=None

10 处理重复列名

如果该参数为True,当列名有重复时,解析列名将变为X, X.1, …, X.N,而不是X, …, X。如果该参数为False,那么当列名中有重复时,前列将会被后列覆盖。

  1. # 布尔型,默认为True  
  2. data = 'a,b,a\n0,1,2\n3,4,5'  
  3. pd.read_csv(StringIO(data), mangle_dupe_cols=True 
  4. # 表头为a b a.1  
  5. # False会报ValueError错误 

11 数据类型 

  1. dtype可以指定各数据列的数据类型。  
  2. # 传入类型名称,或者以列名为键、以指定类型为值的字典  
  3. pd.read_csv(data, dtype=np.float64) # 所有数据均为此数据类型  
  4. pd.read_csv(data, dtype={'c1':np.float64, 'c2': str}) # 指定字段的类型  
  5. pd.read_csv(data, dtype=[datetime, datetime, str, float]) # 依次指定 

12 引擎

使用的分析引擎可以选择C或Python。C语言的速度最快,Python语言的功能最为完善,一般情况下,不需要另行指定。

  1. # 格式为engine=None,其中可选值有{'c', 'python'}  
  2. pd.read_csv(data, engine='c'

13 列数据处理

使用converters参数对列的数据进行转换,参数中指定列名与针对此列的处理函数,最终以字典的形式传入,字典的键可以是列名或者列的序号。

  1. # 字典格式,默认为None  
  2. data = 'x,y\na,1\nb,2'  
  3. def foo(p):  
  4.     return p+'s'  
  5. # x应用函数,y使用lambda  
  6. pd.read_csv(StringIO(data), converters={'x': foo,  
  7.                                         'y': lambda x: x*3})  
  8. # 使用列索引  
  9. pd.read_csv(StringIO(data),  
  10.             converters={0: foo, 1: lambda x: x*3}) 

14 真假值转换

使用true_values和false_values将指定的文本内容转换为True或False,可以用列表指定多个值。

  1. # 列表,默认为None  
  2. data = ('a,b,c\n1,Yes,2\n3,No,4')  
  3. pd.read_csv(StringIO(data),  
  4.             true_values=['Yes'], false_values=['No']) 

15 跳过指定行

如下跳过需要忽略的行数(从文件开始处算起)或需要忽略的行号列表(从0开始):

  1. # 类似列表的序列或者可调用对象  
  2. # 跳过前三行  
  3. pd.read_csv(data, skiprows=2 
  4. # 跳过前三行  
  5. pd.read_csv(data, skiprows=range(2))  
  6. # 跳过指定行  
  7. pd.read_csv(data, skiprows=[24,234,141])  
  8. # 跳过指定行  
  9. pd.read_csv(data, skiprows=np.array([2, 6, 11]))  
  10. # 隔行跳过  
  11. pd.read_csv(data, skiprows=lambda x: x % 2 != 0) 

尾部跳过,从文件尾部开始忽略,C引擎不支持。

  1. # int类型, 默认为0  
  2. pd.read_csv(filename, skipfooter=1) # 最后一行不加载 

skip_blank_lines指定是否跳过空行,如果为True,则跳过空行,否则数据记为NaN。

  1. # 布尔型,默认为True  
  2. # 不跳过空行  
  3. pd.read_csv(data, skip_blank_lines=False

如果skip_blank_lines=True,header参数将忽略空行和注释行, 因此header=0表示第一行数据而非文件的第一行。

16 读取指定行

nrows参数用于指定需要读取的行数,从文件第一行算起,经常用于较大的数据,先取部分进行代码编写。

  1. # int类型,默认为None  
  2. pd.read_csv(data, nrows=1000

17 空值替换

na_values参数的值是一组用于替换NA/NaN的值。如果传参,需要指定特定列的空值。以下值默认会被认定为空值:

  1. ['-1.#IND', '1.#QNAN', '1.#IND', '-1.#QNAN',  
  2.  '#N/A N/A', '#N/A', 'N/A', 'n/a', 'NA',  
  3.  '#NA', 'NULL', 'null', 'NaN', '-NaN',  
  4.  'nan', '-nan', ''] 

使用na_values时需要关注下面keep_default_na的配合使用和影响:

  1. # 可传入标量、字符串、类似列表序列和字典,默认为None  
  2. # 5和5.0会被认为是NaN  
  3. pd.read_csv(data, na_values=[5])  
  4. # ?会被认为是NaN  
  5. pd.read_csv(data, na_values='?' 
  6. # 空值为NaN  
  7. pd.read_csv(data, keep_default_na=Falsena_values=[""])  
  8. # 字符NA和字符0会被认为是NaN  
  9. pd.read_csv(data, keep_default_na=Falsena_values=["NA", "0"])  
  10. # Nope会被认为是NaN 
  11. pd.read_csv(data, na_values=["Nope"])  
  12. # a、b、c均被认为是NaN,等于na_values=['a','b','c']  
  13. pd.read_csv(data, na_values='abc' 
  14. # 指定列的指定值会被认为是NaN  
  15. 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的取值逻辑关系

用Pandas读取CSV,看这篇就够了

  •  说明:如果na_filter为False(默认为True),那么keep_default_na和na_values参数均无效。 
  1. # 布尔型,默认为True  
  2. # 不自动识别空值  
  3. pd.read_csv(data, keep_default_na=False

na_filter为是否检查丢失值(空字符串或空值)。对于大文件来说,数据集中没有空值,设定na_filter=False可以提升读取速度。

  1. # 布尔型,默认为True  
  2. 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" 
  1. # 解析时间的函数名,默认为None  
  2. # 指定时间解析库,默认是dateutil.parser.parser  
  3. date_parser = pd.io.date_converters.parse_date_time 
  4. date_parser = lambda x: pd.to_datetime(x, utc=Trueformat='%d%b%Y' 
  5. date_parser = lambda d: pd.datetime.strptime(d, '%d%b%Y')  
  6. # 使用  
  7. pd.read_csv(data, parse_dates=['年份'], date_parserdate_parser=date_parser) 

parse_dates参数用于对时间日期进行解析。

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

如果infer_datetime_format被设定为True并且parse_dates可用,那么Pandas将尝试转换为日期类型。

  1. # 布尔型,默认为False  
  2. pd.read_csv(data, parse_dates=Trueinfer_datetime_format=True

如果用上文中的parse_dates参数将多列合并并解析成一个时间列,设置keep_date_col的值为True时,会保留这些原有的时间组成列;如果设置为False,则不保留这些列。

  1. # 布尔型,默认为False  
  2. pd.read_csv(data, parse_dates=[[1, 2], [1, 3]], keep_date_col=True

对于DD/MM格式的日期类型,如日期2020-01-06,如果dayfirst=True,则会转换成2020-06-01。

  1. # 布尔型,默认为False  
  2. pd.read_csv(data, dayfirst=Trueparse_dates=[0]) 

cache_dates如果为True,则使用唯一的转换日期缓存来应用datetime转换。解析重复的日期字符串,尤其是带有时区偏移的日期字符串时,可能会大大提高速度。

  1. # 布尔型,默认为True  
  2. pd.read_csv(data, cache_dates=False

20 文件处理

以下是一些对读取文件对象的处理方法。iterator参数如果设置为True,则返回一个TextFileReader对象,并可以对它进行迭代,以便逐块处理文件。

  1. # 布尔型,默认为False  
  2. pd.read_csv(data, iterator=True 
  3. chunksize指定文件块的大小,分块处理大型CSV文件。  
  4. # 整型,默认为None  
  5. pd.read_csv(data, chunksize=100000 
  6. # 分块处理大文件  
  7. df_iterator = pd.read_csv(file, chunksize=50000 
  8. def process_dataframe(df):  
  9.     pass  
  10.     return processed_df  
  11. for index,df_tmp in enumerate(df_iterator):  
  12.     df_processed = process_dataframe(df_tmp)  
  13.     if index > 0:  
  14.        df_processed.to_csv(path)  
  15.     else:  
  16.        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将不进行解压缩。

  1. # 可选值有'infer'、'gzip'、'bz2'、'zip'、'xz'和None,默认为'infer'  
  2. pd.read_csv('sample.tar.gz', compression='gzip'

encoding(编码)指定字符集类型,通常指定为'utf-8'。

  1. # 字符型,默认为None  
  2. pd.read_csv('gairuo.csv', encoding='utf8' 
  3. pd.read_csv("gairuo.csv",encoding="gb2312") # 常见中文 

21 符号

以下是对文件中的一些数据符号进行的特殊识别处理。如下设置千分位分隔符thousands:

  1. # 字符型,默认为None  
  2. pd.read_csv('test.csv', thousands=',') # 逗号分隔 

小数点decimal,识别为小数点的字符。

  1. # 字符串,默认为'.'  
  2. pd.read_csv(data, decimal=","

行结束符lineterminator,将文件分成几行的字符,仅对C解析器有效。

  1. # 长度为1的字符串,默认为None  
  2. data = 'a,b,c~1,2,3~4,5,6'  
  3. pd.read_csv(StringIO(data), lineterminator='~'

引号quotechar,用于表示引用数据的开始和结束的字符。引用的项目可以包含定界符,它将被忽略。

  1. # 长度为1的字符串  
  2. 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模块。

  1. # 整型或者csv.QUOTE_*实例, 默认为0  
  2. import csv  
  3. pd.read_csv('input_file.csv', quoting=csv.QUOTE_NONE) 

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

  1. # 布尔型,默认为True  
  2. import csv  
  3. pd.read_csv('data.csv', quotechar='"'doublequote=Truequoting=csv.QUOTE_NONNUMERIC) 

escapechar可以传入一个转义符,用于过滤数据中的该转入符。比如,如果一行用双引号包裹着的数据中有换行符,用以下代码可以过滤其中的换行符。

  1. # 长度为1的转义字符串,默认为None  
  2. 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。

  1. # 字符串,默认为None  
  2. s = '# notes\na,b,c\n# more notes\n1,2,3'  
  3. pd.read_csv(StringIO(s), sep=','comment='#'skiprows=1

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

  1. # 布尔型,默认为False  
  2. pd.read_csv(StringIO(data), delim_whitespace=False

22 小结

通过本文的介绍,我们了解了读取CSV文件的一些参数的功能,也了解了在读取CSV文件时可以做一些初步的数据整理工作。

原文链接:https://mp.weixin.qq.com/s/gef54I0aMMKvDlepuJA1Hg