Pandas 2.2 中文官方教程和指南(十·二)(3)

简介: Pandas 2.2 中文官方教程和指南(十·二)

Pandas 2.2 中文官方教程和指南(十·二)(2)https://developer.aliyun.com/article/1509787

通用解析配置

dtype 类型名称或列 -> 类型的字典,默认为 None

数据或列的数据类型。例如 {'a': np.float64, 'b': np.int32, 'c': 'Int64'} 使用 strobject 与适当的 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,使用chunksizeiterator参数以块返回数据。(仅适用于 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_naTrue,并且指定了na_values,则na_values将被附加到用于解析的默认 NaN 值上。
  • 如果keep_default_naTrue,并且未指定na_values,则仅使用默认的 NaN 值进行解析。
  • 如果keep_default_naFalse,并且指定了na_values,则仅使用指定的 NaN 值na_values进行解析。
  • 如果keep_default_naFalse,并且未指定na_values,则不会将任何字符串解析为 NaN。

请注意,如果将na_filter传递为False,则将忽略keep_default_nana_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'Nonedict},默认为'infer'

用于在磁盘数据上进行即时解压缩。如果‘infer’,则如果filepath_or_buffer是以‘.gz’、‘.bz2’、‘.zip’、‘.xz’或‘.zst’结尾的路径,则使用 gzip、bz2、zip、xz 或 zstandard,否则不进行解压缩。如果使用'zip',ZIP 文件必须只包含一个要读取的数据文件。设置为None表示不进行解压缩。也可以是一个字典,其中键为'method',设置为其中一个{'zip''gzip''bz2''zstd'},其他键值对转发到zipfile.ZipFilegzip.GzipFilebz2.BZ2Filezstandard.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

如果提供了此参数,它将覆盖以下参数的值(默认或非默认):delimiterdoublequoteescapecharskipinitialspacequotecharquoting。如果需要覆盖值,将发出 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 

如果同时指定了headerskiprowsheader将相对于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。从性能角度考虑,您应该按顺序尝试这些日期解析方法:

  1. 如果知道格式,请使用date_format,例如:date_format="%d/%m/%Y"date_format={column_name: "%d/%m/%Y"}
  2. 如果不同列有不同格式,或者想要将任何额外选项(如utc)传递给to_datetime,则应以object dtype 读取数据,然后使用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

相关文章
|
SQL 数据采集 数据挖掘
Pandas 教程
10月更文挑战第25天
316 2
|
数据采集 存储 数据可视化
Pandas高级教程:数据清洗、转换与分析
Pandas是Python的数据分析库,提供Series和DataFrame数据结构及数据分析工具,便于数据清洗、转换和分析。本教程涵盖Pandas在数据清洗(如缺失值、重复值和异常值处理)、转换(数据类型转换和重塑)和分析(如描述性统计、分组聚合和可视化)的应用。通过学习Pandas,用户能更高效地处理和理解数据,为数据分析任务打下基础。
1558 3
|
存储 JSON 数据格式
Pandas 使用教程 CSV - CSV 转 JSON
Pandas 使用教程 CSV - CSV 转 JSON
224 0
|
JSON 数据格式 Python
Pandas 使用教程 JSON
Pandas 使用教程 JSON
306 0
|
SQL 数据采集 JSON
Pandas 使用教程 Series、DataFrame
Pandas 使用教程 Series、DataFrame
406 0
|
索引 Python
Pandas 2.2 中文官方教程和指南(一)(4)
Pandas 2.2 中文官方教程和指南(一)
255 0
|
存储 SQL JSON
Pandas 2.2 中文官方教程和指南(一)(3)
Pandas 2.2 中文官方教程和指南(一)
307 0
|
XML 关系型数据库 PostgreSQL
Pandas 2.2 中文官方教程和指南(一)(2)
Pandas 2.2 中文官方教程和指南(一)
605 0
|
XML 关系型数据库 MySQL
Pandas 2.2 中文官方教程和指南(一)(1)
Pandas 2.2 中文官方教程和指南(一)
1168 0
|
C++ 索引 Python
Pandas 2.2 中文官方教程和指南(五)(4)
Pandas 2.2 中文官方教程和指南(五)
194 0

热门文章

最新文章