Pandas 2.2 中文官方教程和指南(十·二)(2)https://developer.aliyun.com/article/1509787
通用解析配置
dtype 类型名称或列 -> 类型的字典,默认为 None。
数据或列的数据类型。例如 {'a': np.float64, 'b': np.int32, 'c': 'Int64'} 使用 str 或 object 与适当的 na_values 设置一起使用以保留并不解释 dtype。如果指定了转换器,则将应用转换器而不是 dtype 转换。
版本 1.5.0 中新增功能:支持 defaultdict。指定一个 defaultdict 作为输入,其中默认值确定未明确列出的列的 dtype。
dtype_backend{“numpy_nullable”, “pyarrow”},默认为 NumPy 支持的 DataFrames。
要使用的 dtype_backend,例如 DataFrame 是否应具有 NumPy 数组,当设置“numpy_nullable”时,所有具有可为空实现的 dtype 都使用可为空 dtype,如果设置“pyarrow”,则所有 dtype 都使用 pyarrow。
dtype_backends 仍处于实验阶段。
版本 2.0 中新增。
engine{'c', 'python', 'pyarrow'}
要使用的解析引擎。C 和 pyarrow 引擎更快,而 python 引擎目前更完整。目前只有 pyarrow 引擎支持多线程。
版本 1.4.0 中新增功能:添加了“pyarrow”引擎作为实验性引擎,某些功能不受支持,或者在此引擎下可能无法正常工作。
转换器字典,默认为 None。
用于在某些列中转换值的函数字典。键可以是整数或列标签。
true_values 列表,默认为 None。
要视为 True 的值。
false_values 列表,默认为 None。
要视为 False 的值。
skipinitialspace 布尔值,默认为 False。
在分隔符后跳过空格。
skiprows 类型为列表或整数,默认为 None。
要跳过的行号(从 0 开始)或要跳过的行数(int)文件开头。
如果可调用,可调用函数将针对行索引进行评估,如果应跳过该行则返回 True,否则返回 False:
In [6]: data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3" In [7]: pd.read_csv(StringIO(data)) Out[7]: col1 col2 col3 0 a b 1 1 a b 2 2 c d 3 In [8]: pd.read_csv(StringIO(data), skiprows=lambda x: x % 2 != 0) Out[8]: col1 col2 col3 0 a b 2
skipfooterint,默认为0
要跳过文件底部的行数(在 engine=’c’下不支持)。
nrowsint,默认为None
要读取的文件行数。用于读取大文件的片段。
low_memoryboolean,默认为True
在块中内部处理文件,从而在解析时降低内存使用,但可能混合类型推断。为确保没有混合类型,要么设置为False,要么使用dtype参数指定类型。请注意,无论如何整个文件都会读入单个DataFrame,使用chunksize或iterator参数以块返回数据。(仅适用于 C 解析器)
memory_mapboolean,默认为 False
如果为filepath_or_buffer提供了文件路径,则将文件对象直接映射到内存并直接从那里访问数据。使用��选项可以提高性能,因为不再有任何 I/O 开销。
NA 和缺失数据处理
na_valuesscalar、str、类似列表或字典,默认为None
附加字符串识别为 NA/NaN。如果传递字典,则为每列指定特定的 NA 值。有关默认解释为 NaN 的值列表,请参见 na values const。
keep_default_naboolean,默认为True
是否在解析数据时包括默认的 NaN 值。根据是否传入na_values,行为如下:
- 如果
keep_default_na为True,并且指定了na_values,则na_values将被附加到用于解析的默认 NaN 值上。 - 如果
keep_default_na为True,并且未指定na_values,则仅使用默认的 NaN 值进行解析。 - 如果
keep_default_na为False,并且指定了na_values,则仅使用指定的 NaN 值na_values进行解析。 - 如果
keep_default_na为False,并且未指定na_values,则不会将任何字符串解析为 NaN。
请注意,如果将na_filter传递为False,则将忽略keep_default_na和na_values参数。
na_filterboolean,默认为True
检测缺失值标记(空字符串和 na_values 的值)。在没有任何 NA 的数据中,传递na_filter=False可以提高读取大文件的性能。
verboseboolean,默认为False
指示放置在非数字列中的 NA 值的数量。
skip_blank_linesboolean,默认为True
如果为True,则跳过空行而不是解释为 NaN 值。
日期时间处理
parse_datesboolean 或 int 或名称列表或列表或字典,默认为False。
- 如果为
True-> 尝试解析索引。 - 如果为
[1, 2, 3]-> 尝试将列 1、2、3 分别解析为单独的日期列。 - 如果为
[[1, 3]]-> 合并列 1 和 3 并解析为单个日期列。 - 如果
{'foo': [1, 3]}-> 将列 1、3 解析为日期并调用结果为‘foo’。
注意
存在一个针对 iso8601 格式日期的快速路径。
infer_datetime_format 布尔值,默认为False
如果为True并且为列启用了 parse_dates,则尝试推断日期时间格式以加快处理速度。
自版本 2.0.0 起已弃用:此参数的严格版本现在是默认值,传递它没有任何效果。
keep_date_col 布尔值,默认为False
如果为True并且 parse_dates 指定了组合多个列,则保留原始列。
date_parserfunction,默认为None
用于将一系列字符串列转换为日期时间实例数组的函数。默认使用dateutil.parser.parser进行转换。pandas 将尝试以三种不同的方式调用 date_parser,如果发生异常,则会继续下一个:1) 将一个或多个数组(由 parse_dates 定义)作为参数传递;2) 将由 parse_dates 定义的列中的字符串值(按行)连接成单个数组并传递;3) 对每一行使用一个或多个字符串(对应于由 parse_dates 定义的列)作为参数调用 date_parser。
自版本 2.0.0 起已弃用:改用date_format,或按object读取,然后根据需要应用to_datetime()。
date_formatstr 或列->格式的字典,默认为None
如果与parse_dates一起使用,将根据此格式解析日期。对于更复杂的情况,请按object读取,然后根据需要应用to_datetime()。
自版本 2.0.0 起新增。
dayfirst 布尔值,默认为False
DD/MM 格式日期,国际和欧洲格式。
cache_dates 布尔值,默认为 True
如果为True,则使用一个唯一的转换日期缓存来应用日期时间转换。在解析重复日期字符串时可能会产生显著的加速,特别是带有时区偏移的日期字符串。
迭代
iterator 布尔值,默认为False
返回用于迭代或使用get_chunk()获取块的TextFileReader对象。
chunksizeint,默认为None
返回用于迭代的TextFileReader对象。请参阅下面的迭代和分块。
引用、压缩和文件格式
压缩{'infer','gzip','bz2','zip','xz','zstd',None,dict},默认为'infer'
用于在磁盘数据上进行即时解压缩。如果‘infer’,则如果filepath_or_buffer是以‘.gz’、‘.bz2’、‘.zip’、‘.xz’或‘.zst’结尾的路径,则使用 gzip、bz2、zip、xz 或 zstandard,否则不进行解压缩。如果使用'zip',ZIP 文件必须只包含一个要读取的数据文件。设置为None表示不进行解压缩。也可以是一个字典,其中键为'method',设置为其中一个{'zip'、'gzip'、'bz2'、'zstd'},其他键值对转发到zipfile.ZipFile、gzip.GzipFile、bz2.BZ2File或zstandard.ZstdDecompressor。例如,可以传递以下内容以获得更快的压缩和创建可重现的 gzip 存档:compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1}。
从版本 1.2.0 中更改:以前的版本将‘gzip’的字典条目转发到gzip.open。
thousandsstr,默认为None
千位分隔符。
decimalstr,默认为'.'
用作小数点的字符。例如,欧洲数据可以使用,。
float_precisionstring,默认为 None
指定 C 引擎应使用���个转换器来处理浮点值。选项为None表示普通转换器,high表示高精度转换器,round_trip表示往返转换器。
lineterminatorstr(长度为 1),默认为None
用于将文件分成行的字符。仅与 C 解析器有效。
quotecharstr(长度为 1)
用于表示引用项的开始和结束的字符。引用项可以包括分隔符,它将被忽略。
quotingint 或csv.QUOTE_*实例,默认为0
控制字段引用行为,使用csv.QUOTE_*常量之一。使用QUOTE_MINIMAL(0)、QUOTE_ALL(1)、QUOTE_NONNUMERIC(2)或QUOTE_NONE(3)中的一个。
doublequoteboolean,默认为True
当指定了quotechar并且quoting不是QUOTE_NONE时,指示是否将字段内连续的两个quotechar元素解释为单个quotechar元素。
escapecharstr(长度为 1),默认为None
用于在引用为QUOTE_NONE时转义分隔符的一个字符字符串。
commentstr,默认为None
指示不应解析行的其余部分。如果在行的开头找到,整行将被忽略。此参数必须是一个单个字符。像空行一样(只要skip_blank_lines=True),完全注释的行由参数header忽略,但不由skiprows忽略。例如,如果comment='#',使用header=0解析‘#empty\na,b,c\n1,2,3’将导致‘a,b,c’被视为标题。
encodingstr,默认为None
读取/写入 UTF 时要使用的编码(例如,'utf-8')。Python 标准编码列表。
dialectstr 或csv.Dialect实例,默认为None
如果提供了此参数,它将覆盖以下参数的值(默认或非默认):delimiter、doublequote、escapechar、skipinitialspace、quotechar和quoting。如果需要覆盖值,将发出 ParserWarning。有关更多详细信息,请参阅csv.Dialect文档。
错误处理
on_bad_lines(‘error’,‘warn’,‘skip’),默认为‘error’
指定在遇到错误行(字段过多的行)时要执行的操作。允许的值为:
- ‘error’,在遇到错误行时引发 ParserError。
- ‘warn’,在遇到错误行时打印警告并跳过该行。
- ‘skip’,在遇到错误行时跳过而不引发或警告。
自版本 1.3.0 起新增。
指定列数据类型
您可以指定整个DataFrame或单独的列的数据类型:
In [9]: import numpy as np In [10]: data = "a,b,c,d\n1,2,3,4\n5,6,7,8\n9,10,11" In [11]: print(data) a,b,c,d 1,2,3,4 5,6,7,8 9,10,11 In [12]: df = pd.read_csv(StringIO(data), dtype=object) In [13]: df Out[13]: a b c d 0 1 2 3 4 1 5 6 7 8 2 9 10 11 NaN In [14]: df["a"][0] Out[14]: '1' In [15]: df = pd.read_csv(StringIO(data), dtype={"b": object, "c": np.float64, "d": "Int64"}) In [16]: df.dtypes Out[16]: a int64 b object c float64 d Int64 dtype: object
幸运的是,pandas 提供了多种方法来确保您的列只包含一个dtype。如果您对这些概念不熟悉,您可以在这里了解有关 dtype 的更多信息,并在这里了解有关 pandas 中object转换的更多信息。
例如,您可以使用read_csv()的converters参数:
In [17]: data = "col_1\n1\n2\n'A'\n4.22" In [18]: df = pd.read_csv(StringIO(data), converters={"col_1": str}) In [19]: df Out[19]: col_1 0 1 1 2 2 'A' 3 4.22 In [20]: df["col_1"].apply(type).value_counts() Out[20]: col_1 <class 'str'> 4 Name: count, dtype: int64
或者您可以在读取数据后使用to_numeric()函数强制转换 dtype,
In [21]: df2 = pd.read_csv(StringIO(data)) In [22]: df2["col_1"] = pd.to_numeric(df2["col_1"], errors="coerce") In [23]: df2 Out[23]: col_1 0 1.00 1 2.00 2 NaN 3 4.22 In [24]: df2["col_1"].apply(type).value_counts() Out[24]: col_1 <class 'float'> 4 Name: count, dtype: int64
这将将所有有效解析转换为浮点数,将无效解析保留为NaN。
最终,如何处理包含混合 dtype 的列取决于您的具体需求。在上面的情况下,如果您想要将数据异常值设为NaN,那么to_numeric()可能是您最好的选择。然而,如果您希望所有数据都被强制转换,无论类型如何,那么使用read_csv()的converters参数肯定值得一试。
注意
在某些情况下,读取包含混合 dtype 的列的异常数据将导致数据集不一致。如果您依赖 pandas 推断列的 dtype,解析引擎将会推断数据的不同块的 dtype,而不是一次推断整个数据集的 dtype。因此,您可能会得到包含混合 dtype 的列。例如,
In [25]: col_1 = list(range(500000)) + ["a", "b"] + list(range(500000)) In [26]: df = pd.DataFrame({"col_1": col_1}) In [27]: df.to_csv("foo.csv") In [28]: mixed_df = pd.read_csv("foo.csv") In [29]: mixed_df["col_1"].apply(type).value_counts() Out[29]: col_1 <class 'int'> 737858 <class 'str'> 262144 Name: count, dtype: int64 In [30]: mixed_df["col_1"].dtype Out[30]: dtype('O')
将导致mixed_df包含某些列的int dtype,而由于读取的数据中存在混合 dtype,其他列包含str。重要的是要注意,整体列将标记为object的 dtype,用于包含混合 dtype 的列。
设置dtype_backend="numpy_nullable"将导致每一列都具有可空的 dtype。
In [31]: data = """a,b,c,d,e,f,g,h,i,j ....: 1,2.5,True,a,,,,,12-31-2019, ....: 3,4.5,False,b,6,7.5,True,a,12-31-2019, ....: """ ....: In [32]: df = pd.read_csv(StringIO(data), dtype_backend="numpy_nullable", parse_dates=["i"]) In [33]: df Out[33]: a b c d e f g h i j 0 1 2.5 True a <NA> <NA> <NA> <NA> 2019-12-31 <NA> 1 3 4.5 False b 6 7.5 True a 2019-12-31 <NA> In [34]: df.dtypes Out[34]: a Int64 b Float64 c boolean d string[python] e Int64 f Float64 g boolean h string[python] i datetime64[ns] j Int64 dtype: object ```### 指定分类 dtype 可以通过指定`dtype='category'`或`dtype=CategoricalDtype(categories, ordered)`直接解析`Categorical`列。 ```py In [35]: data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3" In [36]: pd.read_csv(StringIO(data)) Out[36]: col1 col2 col3 0 a b 1 1 a b 2 2 c d 3 In [37]: pd.read_csv(StringIO(data)).dtypes Out[37]: col1 object col2 object col3 int64 dtype: object In [38]: pd.read_csv(StringIO(data), dtype="category").dtypes Out[38]: col1 category col2 category col3 category dtype: object
可以使用字典规范将单独的列解析为Categorical:
In [39]: pd.read_csv(StringIO(data), dtype={"col1": "category"}).dtypes Out[39]: col1 category col2 object col3 int64 dtype: object
指定dtype='category'将导致无序的Categorical,其categories是数据中观察到的唯一值。要对 categories 和顺序进行更多控制,请提前创建CategoricalDtype,并将其传递给该列的dtype。
In [40]: from pandas.api.types import CategoricalDtype In [41]: dtype = CategoricalDtype(["d", "c", "b", "a"], ordered=True) In [42]: pd.read_csv(StringIO(data), dtype={"col1": dtype}).dtypes Out[42]: col1 category col2 object col3 int64 dtype: object
使用dtype=CategoricalDtype时,dtype.categories之外的“意外”值被视为缺失值。
In [43]: dtype = CategoricalDtype(["a", "b", "d"]) # No 'c' In [44]: pd.read_csv(StringIO(data), dtype={"col1": dtype}).col1 Out[44]: 0 a 1 a 2 NaN Name: col1, dtype: category Categories (3, object): ['a', 'b', 'd']
这与Categorical.set_categories()的行为相匹配。
注意
使用dtype='category',生成的 categories 将始终被解析为字符串(object dtype)。如果 categories 是数字,可以使用to_numeric()函数进行转换,或者根据需要使用另一个转换器,如to_datetime()。
当dtype是具有同质categories(全部为数字、全部为日期时间等)的CategoricalDtype时,转换会自动完成。
In [45]: df = pd.read_csv(StringIO(data), dtype="category") In [46]: df.dtypes Out[46]: col1 category col2 category col3 category dtype: object In [47]: df["col3"] Out[47]: 0 1 1 2 2 3 Name: col3, dtype: category Categories (3, object): ['1', '2', '3'] In [48]: new_categories = pd.to_numeric(df["col3"].cat.categories) In [49]: df["col3"] = df["col3"].cat.rename_categories(new_categories) In [50]: df["col3"] Out[50]: 0 1 1 2 2 3 Name: col3, dtype: category Categories (3, int64): [1, 2, 3]
命名和使用列
处理列名
文件可能有或没有标题行。pandas 假定第一行应该用作列名:
In [51]: data = "a,b,c\n1,2,3\n4,5,6\n7,8,9" In [52]: print(data) a,b,c 1,2,3 4,5,6 7,8,9 In [53]: pd.read_csv(StringIO(data)) Out[53]: a b c 0 1 2 3 1 4 5 6 2 7 8 9
通过在header中与names参数一起指定,可以指示要使用的其他名称以及是否丢弃标题行(如果有):
In [54]: print(data) a,b,c 1,2,3 4,5,6 7,8,9 In [55]: pd.read_csv(StringIO(data), names=["foo", "bar", "baz"], header=0) Out[55]: foo bar baz 0 1 2 3 1 4 5 6 2 7 8 9 In [56]: pd.read_csv(StringIO(data), names=["foo", "bar", "baz"], header=None) Out[56]: foo bar baz 0 a b c 1 1 2 3 2 4 5 6 3 7 8 9
如果标题在第一行之外的行中,将行号传递给header。这将跳过前面的行:
In [57]: data = "skip this skip it\na,b,c\n1,2,3\n4,5,6\n7,8,9" In [58]: pd.read_csv(StringIO(data), header=1) Out[58]: a b c 0 1 2 3 1 4 5 6 2 7 8 9
注意
默认行为是推断列名:如果没有传递名称,则行为与header=0相同,并且列名从文件的第一行开始推断,如果显式传递列名,则行为与header=None相同。### 解析重复名称
如果文件或标题包含重复名称,pandas 默认会区分它们,以防止覆盖数据:
In [59]: data = "a,b,a\n0,1,2\n3,4,5" In [60]: pd.read_csv(StringIO(data)) Out[60]: a b a.1 0 0 1 2 1 3 4 5
不再有重复数据,因为重复列‘X’,…,‘X’变为‘X’,‘X.1’,…,‘X.N’。
过滤列(usecols)
usecols参数允许您选择文件中的任何列的子集,可以使用列名称、位置编号或可调用函数:
In [61]: data = "a,b,c,d\n1,2,3,foo\n4,5,6,bar\n7,8,9,baz" In [62]: pd.read_csv(StringIO(data)) Out[62]: a b c d 0 1 2 3 foo 1 4 5 6 bar 2 7 8 9 baz In [63]: pd.read_csv(StringIO(data), usecols=["b", "d"]) Out[63]: b d 0 2 foo 1 5 bar 2 8 baz In [64]: pd.read_csv(StringIO(data), usecols=[0, 2, 3]) Out[64]: a c d 0 1 3 foo 1 4 6 bar 2 7 9 baz In [65]: pd.read_csv(StringIO(data), usecols=lambda x: x.upper() in ["A", "C"]) Out[65]: a c 0 1 3 1 4 6 2 7 9
usecols参数也可用于指定在最终结果中不使用哪些列:
In [66]: pd.read_csv(StringIO(data), usecols=lambda x: x not in ["a", "c"]) Out[66]: b d 0 2 foo 1 5 bar 2 8 baz
在这种情况下,可调用函数指定我们从输出中排除“a”和“c”列。
注释和空行
忽略行注释和空行
如果指定了comment参数,则完全注释的行将被忽略。默认情况下,完全空白行也将被忽略。
In [67]: data = "\na,b,c\n \n# commented line\n1,2,3\n\n4,5,6" In [68]: print(data) a,b,c # commented line 1,2,3 4,5,6 In [69]: pd.read_csv(StringIO(data), comment="#") Out[69]: a b c 0 1 2 3 1 4 5 6
如果skip_blank_lines=False,则read_csv将不会忽略空白行:
In [70]: data = "a,b,c\n\n1,2,3\n\n\n4,5,6" In [71]: pd.read_csv(StringIO(data), skip_blank_lines=False) Out[71]: a b c 0 NaN NaN NaN 1 1.0 2.0 3.0 2 NaN NaN NaN 3 NaN NaN NaN 4 4.0 5.0 6.0
警告
忽略行的存在可能会导致涉及行号的歧义;参数header使用行号(忽略注释/空行),而skiprows使用行号(包括注释/空行):
In [72]: data = "#comment\na,b,c\nA,B,C\n1,2,3" In [73]: pd.read_csv(StringIO(data), comment="#", header=1) Out[73]: A B C 0 1 2 3 In [74]: data = "A,B,C\n#comment\na,b,c\n1,2,3" In [75]: pd.read_csv(StringIO(data), comment="#", skiprows=2) Out[75]: a b c 0 1 2 3
如果同时指定了header和skiprows,header将相对于skiprows的末尾。例如:
In [76]: data = ( ....: "# empty\n" ....: "# second empty line\n" ....: "# third emptyline\n" ....: "X,Y,Z\n" ....: "1,2,3\n" ....: "A,B,C\n" ....: "1,2.,4.\n" ....: "5.,NaN,10.0\n" ....: ) ....: In [77]: print(data) # empty # second empty line # third emptyline X,Y,Z 1,2,3 A,B,C 1,2.,4. 5.,NaN,10.0 In [78]: pd.read_csv(StringIO(data), comment="#", skiprows=4, header=1) Out[78]: A B C 0 1.0 2.0 4.0 1 5.0 NaN 10.0 ```#### 注释 有时文件中可能包含注释或元数据: ```py In [79]: data = ( ....: "ID,level,category\n" ....: "Patient1,123000,x # really unpleasant\n" ....: "Patient2,23000,y # wouldn't take his medicine\n" ....: "Patient3,1234018,z # awesome" ....: ) ....: In [80]: with open("tmp.csv", "w") as fh: ....: fh.write(data) ....: In [81]: print(open("tmp.csv").read()) ID,level,category Patient1,123000,x # really unpleasant Patient2,23000,y # wouldn't take his medicine Patient3,1234018,z # awesome
默认情况下,解析器会在输出中包含注释:
In [82]: df = pd.read_csv("tmp.csv") In [83]: df Out[83]: ID level category 0 Patient1 123000 x # really unpleasant 1 Patient2 23000 y # wouldn't take his medicine 2 Patient3 1234018 z # awesome
我们可以使用comment关键字来抑制注释:
In [84]: df = pd.read_csv("tmp.csv", comment="#") In [85]: df Out[85]: ID level category 0 Patient1 123000 x 1 Patient2 23000 y 2 Patient3 1234018 z ```### 处理 Unicode 数据 应该使用`encoding`参数来处理编码的 Unicode 数据,这将导致字节字符串在结果中被解码为 Unicode: ```py In [86]: from io import BytesIO In [87]: data = b"word,length\n" b"Tr\xc3\xa4umen,7\n" b"Gr\xc3\xbc\xc3\x9fe,5" In [88]: data = data.decode("utf8").encode("latin-1") In [89]: df = pd.read_csv(BytesIO(data), encoding="latin-1") In [90]: df Out[90]: word length 0 Träumen 7 1 Grüße 5 In [91]: df["word"][1] Out[91]: 'Grüße'
一些将所有字符编码为多字节的格式,如 UTF-16,如果不指定编码,将无法正确解析。 Python 标准编码的完整列表。 ### 索引列和尾随分隔符
如果文件的数据列数比列名多一个,第一列将被用作DataFrame的行名:
In [92]: data = "a,b,c\n4,apple,bat,5.7\n8,orange,cow,10" In [93]: pd.read_csv(StringIO(data)) Out[93]: a b c 4 apple bat 5.7 8 orange cow 10.0
In [94]: data = "index,a,b,c\n4,apple,bat,5.7\n8,orange,cow,10" In [95]: pd.read_csv(StringIO(data), index_col=0) Out[95]: a b c index 4 apple bat 5.7 8 orange cow 10.0
通常,您可以使用index_col选项来实现此行为。
当文件在每个数据行末尾都有分隔符时,解析器会产生一些异常情况,导致解析混乱。为了显式禁用索引列推断并丢弃最后一列,传递index_col=False:
In [96]: data = "a,b,c\n4,apple,bat,\n8,orange,cow," In [97]: print(data) a,b,c 4,apple,bat, 8,orange,cow, In [98]: pd.read_csv(StringIO(data)) Out[98]: a b c 4 apple bat NaN 8 orange cow NaN In [99]: pd.read_csv(StringIO(data), index_col=False) Out[99]: a b c 0 4 apple bat 1 8 orange cow
如果使用usecols选项解析数据的子集,则index_col规范基于该子集,而不是原始数据。
In [100]: data = "a,b,c\n4,apple,bat,\n8,orange,cow," In [101]: print(data) a,b,c 4,apple,bat, 8,orange,cow, In [102]: pd.read_csv(StringIO(data), usecols=["b", "c"]) Out[102]: b c 4 bat NaN 8 cow NaN In [103]: pd.read_csv(StringIO(data), usecols=["b", "c"], index_col=0) Out[103]: b c 4 bat NaN 8 cow NaN ```### 日期处理 #### 指定日期列 为了更好地处理日期时间数据,`read_csv()`使用关键字参数`parse_dates`和`date_format`允许用户指定各种列和日期/时间格式将输入文本数据转换为`datetime`对象。 最简单的情况是只需传入`parse_dates=True`: ```py In [104]: with open("foo.csv", mode="w") as f: .....: f.write("date,A,B,C\n20090101,a,1,2\n20090102,b,3,4\n20090103,c,4,5") .....: # Use a column as an index, and parse it as dates. In [105]: df = pd.read_csv("foo.csv", index_col=0, parse_dates=True) In [106]: df Out[106]: A B C date 2009-01-01 a 1 2 2009-01-02 b 3 4 2009-01-03 c 4 5 # These are Python datetime objects In [107]: df.index Out[107]: DatetimeIndex(['2009-01-01', '2009-01-02', '2009-01-03'], dtype='datetime64[ns]', name='date', freq=None)
通常情况下,我们可能希望将日期和时间数据分开存储,或将各种日期字段分开存储。 parse_dates关键字可用于指定要从中解析日期和/或时间的列的组合。
您可以指定一个列列表的列表给parse_dates,生成的日期列将被预置到输出中(以不影响现有列顺序)且新列名将是组件列名的连接:
In [108]: data = ( .....: "KORD,19990127, 19:00:00, 18:56:00, 0.8100\n" .....: "KORD,19990127, 20:00:00, 19:56:00, 0.0100\n" .....: "KORD,19990127, 21:00:00, 20:56:00, -0.5900\n" .....: "KORD,19990127, 21:00:00, 21:18:00, -0.9900\n" .....: "KORD,19990127, 22:00:00, 21:56:00, -0.5900\n" .....: "KORD,19990127, 23:00:00, 22:56:00, -0.5900" .....: ) .....: In [109]: with open("tmp.csv", "w") as fh: .....: fh.write(data) .....: In [110]: df = pd.read_csv("tmp.csv", header=None, parse_dates=[[1, 2], [1, 3]]) In [111]: df Out[111]: 1_2 1_3 0 4 0 1999-01-27 19:00:00 1999-01-27 18:56:00 KORD 0.81 1 1999-01-27 20:00:00 1999-01-27 19:56:00 KORD 0.01 2 1999-01-27 21:00:00 1999-01-27 20:56:00 KORD -0.59 3 1999-01-27 21:00:00 1999-01-27 21:18:00 KORD -0.99 4 1999-01-27 22:00:00 1999-01-27 21:56:00 KORD -0.59 5 1999-01-27 23:00:00 1999-01-27 22:56:00 KORD -0.59
默认情况下,解析器会删除组件日期列,但您可以通过keep_date_col关键字选择保留它们:
In [112]: df = pd.read_csv( .....: "tmp.csv", header=None, parse_dates=[[1, 2], [1, 3]], keep_date_col=True .....: ) .....: In [113]: df Out[113]: 1_2 1_3 0 ... 2 3 4 0 1999-01-27 19:00:00 1999-01-27 18:56:00 KORD ... 19:00:00 18:56:00 0.81 1 1999-01-27 20:00:00 1999-01-27 19:56:00 KORD ... 20:00:00 19:56:00 0.01 2 1999-01-27 21:00:00 1999-01-27 20:56:00 KORD ... 21:00:00 20:56:00 -0.59 3 1999-01-27 21:00:00 1999-01-27 21:18:00 KORD ... 21:00:00 21:18:00 -0.99 4 1999-01-27 22:00:00 1999-01-27 21:56:00 KORD ... 22:00:00 21:56:00 -0.59 5 1999-01-27 23:00:00 1999-01-27 22:56:00 KORD ... 23:00:00 22:56:00 -0.59 [6 rows x 7 columns]
请注意,如果您希望将多个列合并为单个日期列,则必须使用嵌套列表。换句话说,parse_dates=[1, 2]表示第二列和第三列应分别解析为单独的日期列,而parse_dates=[[1, 2]]表示两列应解析为单个列。
您还可以使用字典指定自定义名称列:
In [114]: date_spec = {"nominal": [1, 2], "actual": [1, 3]} In [115]: df = pd.read_csv("tmp.csv", header=None, parse_dates=date_spec) In [116]: df Out[116]: nominal actual 0 4 0 1999-01-27 19:00:00 1999-01-27 18:56:00 KORD 0.81 1 1999-01-27 20:00:00 1999-01-27 19:56:00 KORD 0.01 2 1999-01-27 21:00:00 1999-01-27 20:56:00 KORD -0.59 3 1999-01-27 21:00:00 1999-01-27 21:18:00 KORD -0.99 4 1999-01-27 22:00:00 1999-01-27 21:56:00 KORD -0.59 5 1999-01-27 23:00:00 1999-01-27 22:56:00 KORD -0.59
重要的是要记住,如果要将多个文本列解析为单个日期列,则会在数据前添加一个新列。index_col规范是基于这组新列而不是原始数据列:
In [117]: date_spec = {"nominal": [1, 2], "actual": [1, 3]} In [118]: df = pd.read_csv( .....: "tmp.csv", header=None, parse_dates=date_spec, index_col=0 .....: ) # index is the nominal column .....: In [119]: df Out[119]: actual 0 4 nominal 1999-01-27 19:00:00 1999-01-27 18:56:00 KORD 0.81 1999-01-27 20:00:00 1999-01-27 19:56:00 KORD 0.01 1999-01-27 21:00:00 1999-01-27 20:56:00 KORD -0.59 1999-01-27 21:00:00 1999-01-27 21:18:00 KORD -0.99 1999-01-27 22:00:00 1999-01-27 21:56:00 KORD -0.59 1999-01-27 23:00:00 1999-01-27 22:56:00 KORD -0.59
注意
如果列或索引包含无法解析的日期,则整个列或索引将不经更改地返回为对象数据类型。对于非标准日期时间解析,请在pd.read_csv后使用to_datetime()。
注意
read_csv 对 iso8601 格式的日期时间字符串有一个快速路���,例如“2000-01-01T00:01:02+00:00”和类似变体。如果您可以安排数据以这种格式存储日期时间,加载时间将显着更快,已观察到约 20 倍的速度。
自版本 2.2.0 起已弃用:在 read_csv 中合并日期列已弃用。请改为在相关结果列上使用pd.to_datetime。
日期解析函数
最后,解析器允许您指定自定义的date_format。从性能角度考虑,您应该按顺序尝试这些日期解析方法:
- 如果知道格式,请使用
date_format,例如:date_format="%d/%m/%Y"或date_format={column_name: "%d/%m/%Y"}。 - 如果不同列有不同格式,或者想要将任何额外选项(如
utc)传递给to_datetime,则应以objectdtype 读取数据,然后使用to_datetime。
解析具有混合时区的 CSV
pandas 无法本地表示具有混合时区的列或索引。如果您的 CSV 文件包含具有混合时区的列,则默认结果将是一个对象 dtype 列,其中包含字符串,即使使用parse_dates也是如此。要将混合时区值解析为日期时间列,请以object dtype 读取,然后调用to_datetime()并使用utc=True。
In [120]: content = """\ .....: a .....: 2000-01-01T00:00:00+05:00 .....: 2000-01-01T00:00:00+06:00""" .....: In [121]: df = pd.read_csv(StringIO(content)) In [122]: df["a"] = pd.to_datetime(df["a"], utc=True) In [123]: df["a"] Out[123]: 0 1999-12-31 19:00:00+00:00 1 1999-12-31 18:00:00+00:00 Name: a, dtype: datetime64[ns, UTC] ```#### 推断日期时间格式 这里有一些可以猜测的日期时间字符串示例(均表示 2011 年 12 月 30 日 00:00:00): + “20111230” + “2011/12/30” + “20111230 00:00:00” + “12/30/2011 00:00:00” + “30/Dec/2011 00:00:00” + “30/December/2011 00:00:00” 请注意,格式推断对`dayfirst`很敏感。使用`dayfirst=True`,它会猜测“01/12/2011”为 12 月 1 日。使用`dayfirst=False`(默认),它会猜测“01/12/2011”为 1 月 12 日。 如果尝试解析日期字符串列,pandas 将尝试从第一个非 NaN 元素猜测格式,然后使用该格式解析列的其余部分。如果 pandas 无法猜测格式(例如,如果您的第一个字符串是`'01 December US/Pacific 2000'`),则会发出警告,并且每行将通过`dateutil.parser.parse`单独解析。解析日期的最安全方式是显式设置`format=`。 ```py In [124]: df = pd.read_csv( .....: "foo.csv", .....: index_col=0, .....: parse_dates=True, .....: ) .....: In [125]: df Out[125]: A B C date 2009-01-01 a 1 2 2009-01-02 b 3 4 2009-01-03 c 4 5
如果同一列中有混合的日期时间格式,可以传递format='mixed'
In [126]: data = StringIO("date\n12 Jan 2000\n2000-01-13\n") In [127]: df = pd.read_csv(data) In [128]: df['date'] = pd.to_datetime(df['date'], format='mixed') In [129]: df Out[129]: date 0 2000-01-12 1 2000-01-13
或者,如果您的日期时间格式都是 ISO8601(可能不是完全相同的格式):
In [130]: data = StringIO("date\n2020-01-01\n2020-01-01 03:00\n") In [131]: df = pd.read_csv(data) In [132]: df['date'] = pd.to_datetime(df['date'], format='ISO8601') In [133]: df Out[133]: date 0 2020-01-01 00:00:00 1 2020-01-01 03:00:00
Pandas 2.2 中文官方教程和指南(十·二)(4)https://developer.aliyun.com/article/1509789