PyArrow 功能
pandas 可以利用PyArrow来扩展功能并改善各种 API 的性能。这包括:
- 与 NumPy 相比,拥有更广泛的数据类型
- 对所有数据类型支持缺失数据(NA)
- 高性能 IO 读取器集成
- 便于与基于 Apache Arrow 规范的其他数据框架库(例如 polars、cuDF)进行互操作性
要使用此功能,请确保您已经安装了最低支持的 PyArrow 版本。
数据结构集成
一个Series
、Index
或DataFrame
的列可以直接由pyarrow.ChunkedArray
支持,这类似于 NumPy 数组。要从主要的 pandas 数据结构构造这些,您可以在dtype
参数中传入类型后跟[pyarrow]
的字符串,例如"int64[pyarrow]"
。
In [1]: ser = pd.Series([-1.5, 0.2, None], dtype="float32[pyarrow]") In [2]: ser Out[2]: 0 -1.5 1 0.2 2 <NA> dtype: float[pyarrow] In [3]: idx = pd.Index([True, None], dtype="bool[pyarrow]") In [4]: idx Out[4]: Index([True, <NA>], dtype='bool[pyarrow]') In [5]: df = pd.DataFrame([[1, 2], [3, 4]], dtype="uint64[pyarrow]") In [6]: df Out[6]: 0 1 0 1 2 1 3 4
注意
字符串别名"string[pyarrow]"
映射到pd.StringDtype("pyarrow")
,这与指定dtype=pd.ArrowDtype(pa.string())
不等效。通常,对数据的操作行为会类似,除了pd.StringDtype("pyarrow")
可以返回基于 NumPy 的可空类型,而pd.ArrowDtype(pa.string())
将返回ArrowDtype
。
In [7]: import pyarrow as pa In [8]: data = list("abc") In [9]: ser_sd = pd.Series(data, dtype="string[pyarrow]") In [10]: ser_ad = pd.Series(data, dtype=pd.ArrowDtype(pa.string())) In [11]: ser_ad.dtype == ser_sd.dtype Out[11]: False In [12]: ser_sd.str.contains("a") Out[12]: 0 True 1 False 2 False dtype: boolean In [13]: ser_ad.str.contains("a") Out[13]: 0 True 1 False 2 False dtype: bool[pyarrow]
对于接受参数的 PyArrow 类型,您可以将带有这些参数的 PyArrow 类型传入ArrowDtype
以在dtype
参数中使用。
In [14]: import pyarrow as pa In [15]: list_str_type = pa.list_(pa.string()) In [16]: ser = pd.Series([["hello"], ["there"]], dtype=pd.ArrowDtype(list_str_type)) In [17]: ser Out[17]: 0 ['hello'] 1 ['there'] dtype: list<item: string>[pyarrow]
In [18]: from datetime import time In [19]: idx = pd.Index([time(12, 30), None], dtype=pd.ArrowDtype(pa.time64("us"))) In [20]: idx Out[20]: Index([12:30:00, <NA>], dtype='time64[us][pyarrow]')
In [21]: from decimal import Decimal In [22]: decimal_type = pd.ArrowDtype(pa.decimal128(3, scale=2)) In [23]: data = [[Decimal("3.19"), None], [None, Decimal("-1.23")]] In [24]: df = pd.DataFrame(data, dtype=decimal_type) In [25]: df Out[25]: 0 1 0 3.19 <NA> 1 <NA> -1.23
如果您已经有一个pyarrow.Array
或pyarrow.ChunkedArray
,您可以将其传入arrays.ArrowExtensionArray
以构造相关的Series
、Index
或DataFrame
对象。
In [26]: pa_array = pa.array( ....: [{"1": "2"}, {"10": "20"}, None], ....: type=pa.map_(pa.string(), pa.string()), ....: ) ....: In [27]: ser = pd.Series(pd.arrays.ArrowExtensionArray(pa_array)) In [28]: ser Out[28]: 0 [('1', '2')] 1 [('10', '20')] 2 <NA> dtype: map<string, string>[pyarrow]
要从Series
或Index
中检索一个 pyarrow pyarrow.ChunkedArray
,您可以在Series
或Index
上调用 pyarrow 数组构造函数。
In [29]: ser = pd.Series([1, 2, None], dtype="uint8[pyarrow]") In [30]: pa.array(ser) Out[30]: <pyarrow.lib.UInt8Array object at 0x7ff2a2968400> [ 1, 2, null ] In [31]: idx = pd.Index(ser) In [32]: pa.array(idx) Out[32]: <pyarrow.lib.UInt8Array object at 0x7ff2a2968460> [ 1, 2, null ]
要将 pyarrow.Table
转换为 DataFrame
,您可以使用 types_mapper=pd.ArrowDtype
调用 pyarrow.Table.to_pandas()
方法。
In [33]: table = pa.table([pa.array([1, 2, 3], type=pa.int64())], names=["a"]) In [34]: df = table.to_pandas(types_mapper=pd.ArrowDtype) In [35]: df Out[35]: a 0 1 1 2 2 3 In [36]: df.dtypes Out[36]: a int64[pyarrow] dtype: object
操作
PyArrow 数据结构集成是通过 pandas 的 ExtensionArray
接口 实现的;因此,在 pandas API 中集成了此接口的地方存在支持的功能。此外,当可用时,此功能通过 PyArrow compute functions 加速。这包括:
- 数值聚合
- 数值运算
- 数值舍入
- 逻辑和比较函数
- 字符串功能
- 日期时间功能
以下只是一些由本机 PyArrow 计算函数加速的操作示例。
In [37]: import pyarrow as pa In [38]: ser = pd.Series([-1.545, 0.211, None], dtype="float32[pyarrow]") In [39]: ser.mean() Out[39]: -0.6669999808073044 In [40]: ser + ser Out[40]: 0 -3.09 1 0.422 2 <NA> dtype: float[pyarrow] In [41]: ser > (ser + 1) Out[41]: 0 False 1 False 2 <NA> dtype: bool[pyarrow] In [42]: ser.dropna() Out[42]: 0 -1.545 1 0.211 dtype: float[pyarrow] In [43]: ser.isna() Out[43]: 0 False 1 False 2 True dtype: bool In [44]: ser.fillna(0) Out[44]: 0 -1.545 1 0.211 2 0.0 dtype: float[pyarrow]
In [45]: ser_str = pd.Series(["a", "b", None], dtype=pd.ArrowDtype(pa.string())) In [46]: ser_str.str.startswith("a") Out[46]: 0 True 1 False 2 <NA> dtype: bool[pyarrow]
In [47]: from datetime import datetime In [48]: pa_type = pd.ArrowDtype(pa.timestamp("ns")) In [49]: ser_dt = pd.Series([datetime(2022, 1, 1), None], dtype=pa_type) In [50]: ser_dt.dt.strftime("%Y-%m") Out[50]: 0 2022-01 1 <NA> dtype: string[pyarrow]
I/O 读取
PyArrow 还提供了已集成到几个 pandas IO 读取器中的 IO 读取功能。以下函数提供了一个 engine
关键字,可以调度到 PyArrow 以加速从 IO 源读取。
read_csv()
read_json()
read_orc()
read_feather()
In [51]: import io In [52]: data = io.StringIO("""a,b,c ....: 1,2.5,True ....: 3,4.5,False ....: """) ....: In [53]: df = pd.read_csv(data, engine="pyarrow") In [54]: df Out[54]: a b c 0 1 2.5 True 1 3 4.5 False
默认情况下,这些函数和所有其他 IO 读取器函数返回 NumPy 支持的数据。这些读取器可以通过指定参数 dtype_backend="pyarrow"
返回 PyArrow 支持的数据。读取器不需要设置 engine="pyarrow"
来必然返回 PyArrow 支持的数据。
In [55]: import io In [56]: data = io.StringIO("""a,b,c,d,e,f,g,h,i ....: 1,2.5,True,a,,,,, ....: 3,4.5,False,b,6,7.5,True,a, ....: """) ....: In [57]: df_pyarrow = pd.read_csv(data, dtype_backend="pyarrow") In [58]: df_pyarrow.dtypes Out[58]: a int64[pyarrow] b double[pyarrow] c bool[pyarrow] d string[pyarrow] e int64[pyarrow] f double[pyarrow] g bool[pyarrow] h string[pyarrow] i null[pyarrow] dtype: object
还有几个非 IO 读取器函数也可以使用 dtype_backend
参数返回 PyArrow 支持的数据,包括:
to_numeric()
DataFrame.convert_dtypes()
Series.convert_dtypes()
数据结构集成
一个Series
、Index
或DataFrame
的列可以直接由一个类似于 NumPy 数组的pyarrow.ChunkedArray
支持,要从主要的 pandas���据结构构造这些对象,您可以在类型后面加上[pyarrow]
的字符串,例如"int64[pyarrow]"
传递给dtype
参数
In [1]: ser = pd.Series([-1.5, 0.2, None], dtype="float32[pyarrow]") In [2]: ser Out[2]: 0 -1.5 1 0.2 2 <NA> dtype: float[pyarrow] In [3]: idx = pd.Index([True, None], dtype="bool[pyarrow]") In [4]: idx Out[4]: Index([True, <NA>], dtype='bool[pyarrow]') In [5]: df = pd.DataFrame([[1, 2], [3, 4]], dtype="uint64[pyarrow]") In [6]: df Out[6]: 0 1 0 1 2 1 3 4
注意
字符串别名"string[pyarrow]"
映射到pd.StringDtype("pyarrow")
,这与指定dtype=pd.ArrowDtype(pa.string())
不等效。通常,对数据的操作行为类似,除了pd.StringDtype("pyarrow")
可以返回基于 NumPy 的可空类型,而pd.ArrowDtype(pa.string())
将返回ArrowDtype
。
In [7]: import pyarrow as pa In [8]: data = list("abc") In [9]: ser_sd = pd.Series(data, dtype="string[pyarrow]") In [10]: ser_ad = pd.Series(data, dtype=pd.ArrowDtype(pa.string())) In [11]: ser_ad.dtype == ser_sd.dtype Out[11]: False In [12]: ser_sd.str.contains("a") Out[12]: 0 True 1 False 2 False dtype: boolean In [13]: ser_ad.str.contains("a") Out[13]: 0 True 1 False 2 False dtype: bool[pyarrow]
对于接受参数的 PyArrow 类型,您可以将带有这些参数的 PyArrow 类型传递给ArrowDtype
以在dtype
参数中使用。
In [14]: import pyarrow as pa In [15]: list_str_type = pa.list_(pa.string()) In [16]: ser = pd.Series([["hello"], ["there"]], dtype=pd.ArrowDtype(list_str_type)) In [17]: ser Out[17]: 0 ['hello'] 1 ['there'] dtype: list<item: string>[pyarrow]
In [18]: from datetime import time In [19]: idx = pd.Index([time(12, 30), None], dtype=pd.ArrowDtype(pa.time64("us"))) In [20]: idx Out[20]: Index([12:30:00, <NA>], dtype='time64[us][pyarrow]')
In [21]: from decimal import Decimal In [22]: decimal_type = pd.ArrowDtype(pa.decimal128(3, scale=2)) In [23]: data = [[Decimal("3.19"), None], [None, Decimal("-1.23")]] In [24]: df = pd.DataFrame(data, dtype=decimal_type) In [25]: df Out[25]: 0 1 0 3.19 <NA> 1 <NA> -1.23
如果您已经有一个pyarrow.Array
或pyarrow.ChunkedArray
,您可以将其传递给arrays.ArrowExtensionArray
以构造相关的Series
、Index
或DataFrame
对象。
In [26]: pa_array = pa.array( ....: [{"1": "2"}, {"10": "20"}, None], ....: type=pa.map_(pa.string(), pa.string()), ....: ) ....: In [27]: ser = pd.Series(pd.arrays.ArrowExtensionArray(pa_array)) In [28]: ser Out[28]: 0 [('1', '2')] 1 [('10', '20')] 2 <NA> dtype: map<string, string>[pyarrow]
要从Series
或Index
中检索一个 pyarrow pyarrow.ChunkedArray
,您可以在Series
或Index
上调用 pyarrow 数组构造函数。
In [29]: ser = pd.Series([1, 2, None], dtype="uint8[pyarrow]") In [30]: pa.array(ser) Out[30]: <pyarrow.lib.UInt8Array object at 0x7ff2a2968400> [ 1, 2, null ] In [31]: idx = pd.Index(ser) In [32]: pa.array(idx) Out[32]: <pyarrow.lib.UInt8Array object at 0x7ff2a2968460> [ 1, 2, null ]
要将pyarrow.Table
转换为DataFrame
,您可以使用types_mapper=pd.ArrowDtype
调用pyarrow.Table.to_pandas()
方法。
In [33]: table = pa.table([pa.array([1, 2, 3], type=pa.int64())], names=["a"]) In [34]: df = table.to_pandas(types_mapper=pd.ArrowDtype) In [35]: df Out[35]: a 0 1 1 2 2 3 In [36]: df.dtypes Out[36]: a int64[pyarrow] dtype: object
操作
PyArrow 数据结构集成是通过 pandas 的ExtensionArray
接口实现的;因此,在 pandas API 中集成了此接口的地方存在支持的功能。此外,此功能在可用时通过 PyArrow compute functions加速。这包括:
- 数值聚合
- 数值运算
- 数值舍入
- 逻辑和比较函数
- 字符串功能
- 日期时间功能
以下只是一些由本机 PyArrow 计算函数加速的操作示例。
In [37]: import pyarrow as pa In [38]: ser = pd.Series([-1.545, 0.211, None], dtype="float32[pyarrow]") In [39]: ser.mean() Out[39]: -0.6669999808073044 In [40]: ser + ser Out[40]: 0 -3.09 1 0.422 2 <NA> dtype: float[pyarrow] In [41]: ser > (ser + 1) Out[41]: 0 False 1 False 2 <NA> dtype: bool[pyarrow] In [42]: ser.dropna() Out[42]: 0 -1.545 1 0.211 dtype: float[pyarrow] In [43]: ser.isna() Out[43]: 0 False 1 False 2 True dtype: bool In [44]: ser.fillna(0) Out[44]: 0 -1.545 1 0.211 2 0.0 dtype: float[pyarrow]
In [45]: ser_str = pd.Series(["a", "b", None], dtype=pd.ArrowDtype(pa.string())) In [46]: ser_str.str.startswith("a") Out[46]: 0 True 1 False 2 <NA> dtype: bool[pyarrow]
In [47]: from datetime import datetime In [48]: pa_type = pd.ArrowDtype(pa.timestamp("ns")) In [49]: ser_dt = pd.Series([datetime(2022, 1, 1), None], dtype=pa_type) In [50]: ser_dt.dt.strftime("%Y-%m") Out[50]: 0 2022-01 1 <NA> dtype: string[pyarrow]
I/O 读取
PyArrow 还提供了已集成到几个 pandas IO 读取器中的 IO 读取功能。以下函数提供了一个engine
关键字,可以调度到 PyArrow 以加速从 IO 源读取。
read_csv()
read_json()
read_orc()
read_feather()
In [51]: import io In [52]: data = io.StringIO("""a,b,c ....: 1,2.5,True ....: 3,4.5,False ....: """) ....: In [53]: df = pd.read_csv(data, engine="pyarrow") In [54]: df Out[54]: a b c 0 1 2.5 True 1 3 4.5 False
默认情况下,这些函数和所有其他 IO 读取函数返回 NumPy 支持的数据。通过指定参数dtype_backend="pyarrow"
,这些读取器可以返回 PyArrow 支持的数据。读取器不需要设置engine="pyarrow"
来必然返回 PyArrow 支持的数据。
In [55]: import io In [56]: data = io.StringIO("""a,b,c,d,e,f,g,h,i ....: 1,2.5,True,a,,,,, ....: 3,4.5,False,b,6,7.5,True,a, ....: """) ....: In [57]: df_pyarrow = pd.read_csv(data, dtype_backend="pyarrow") In [58]: df_pyarrow.dtypes Out[58]: a int64[pyarrow] b double[pyarrow] c bool[pyarrow] d string[pyarrow] e int64[pyarrow] f double[pyarrow] g bool[pyarrow] h string[pyarrow] i null[pyarrow] dtype: object
还有一些非 IO 读取函数也可以使用dtype_backend
参数返回 PyArrow 支持的数据,包括:
to_numeric()
DataFrame.convert_dtypes()
Series.convert_dtypes()
索引和选择数据
pandas 对象中的轴标签信息具有多种用途:
- 使用已知指标标识数据(即提供 元数据),对于分析、可视化和交互式控制台显示非常重要。
- 启用自动和明确的数据对齐。
- 允许直观地获取和设置数据集的子集。
在本节中,我们将重点放在最后一点上:即如何切片、切块和通常获取和设置 pandas 对象的子集。���要关注将放在 Series 和 DataFrame 上,因为它们在这个领域接受了更多的开发关注。
注意
Python 和 NumPy 索引运算符 []
和属性运算符 .
提供了对 pandas 数据结构的快速简便访问,适用于各种用例。这使得交互式工作变得直观,因为如果你已经知道如何处理 Python 字典和 NumPy 数组,那么学习成本很低。然而,由于要访问的数据类型事先未知,直接使用标准运算符存在一些优化限制。对于生产代码,我们建议您利用本章节中提供的优化的 pandas 数据访问方法。
警告
对于设置操作,返回的是副本还是引用,可能取决于上下文。有时这被称为 chained assignment
,应该避免。请参阅返回视图与副本。
在 MultiIndex / 高级索引中查看 MultiIndex
和更高级的索引文档。
在食谱中查看一些高级策略。
不同的索引选择
为了支持更明确的基于位置的索引,对象选择已经增加了一些用户请求的内容。pandas 现在支持三种类型的多轴索引。
.loc
主要基于标签,但也可以与布尔数组一起使用。当未找到项目时,.loc
会引发KeyError
。允许的输入包括:
- 单个标签,例如
5
或'a'
(请注意,5
被解释为索引的 标签。这种用法不是索引上的整数位置。)。- 一个标签列表或数组
['a', 'b', 'c']
。- 一个带有标签
'a':'f'
的切片对象(请注意,与通常的 Python 切片相反,开始和停止都包括在内,当存在于索引中时!请参阅使用标签切片和端点是包含的。)- 布尔数组(任何
NA
值将被视为False
)。- 一个带有一个参数(调用的 Series 或 DataFrame)的
callable
函数,并返回用于索引的有效输出(上述之一)。- 一个包含上述输入之一的行(和列)索引的元组。
- 在按标签选择中查看更多信息。
.iloc
主要基于整数位置(从轴的0
到length-1
),但也可以与布尔数组一起使用。如果请求的索引器超出范围,.iloc
将引发IndexError
,除了切片索引器允许超出范围索引(这符合 Python/NumPy 的切片语义)。允许的输入为:
- 一个整数,例如
5
。- 整数列表或数组
[4, 3, 0]
。- 一个包含整数
1:7
的切片对象。- 布尔数组(任何
NA
值将被视为False
)。- 一个带有一个参数(调用的 Series 或 DataFrame)的
callable
函数,并返回用于索引的有效输出(上述之一)。- 一个包含行(和列)索引的元组,其元素是上述输入之一。
- 查看更多内容请参考按位置选择,高级索引和高级分层。
.loc
、.iloc
,以及[]
索引可以接受callable
作为索引器。查看更多内容请参考按 callable 选择。
注意
将元组键解构为行(和列)索引发生在调用可调用函数之前,因此您不能从可调用函数返回元组以同时索引���和列。
从具有多轴选择的对象获取值使用以下表示法(以.loc
为例,但以下内容也适用于.iloc
)。任何轴访问器都可以是空切片:
。规范中省略的轴被假定为:
,例如p.loc['a']
等同于p.loc['a', :]
。
对象类型 | 索引器 |
Series | s.loc[indexer] |
| DataFrame | df.loc[row_indexer,column_indexer]
| ## 基础知识
如在上一节介绍数据结构时提到的,使用[]
进行索引(在 Python 中实现类行为的熟悉者称之为__getitem__
)的主要功能是选择出低维度切片。下表显示了使用[]
对 pandas 对象进行索引时的返回类型值:
对象类型 | 选择 | 返回值类型 |
Series | series[label] |
标量值 |
DataFrame | frame[colname] |
与 colname 对应的Series |
这里我们构建一个简单的时间序列数据集,用于说明索引功能:
In [1]: dates = pd.date_range('1/1/2000', periods=8) In [2]: df = pd.DataFrame(np.random.randn(8, 4), ...: index=dates, columns=['A', 'B', 'C', 'D']) ...: In [3]: df Out[3]: A B C D 2000-01-01 0.469112 -0.282863 -1.509059 -1.135632 2000-01-02 1.212112 -0.173215 0.119209 -1.044236 2000-01-03 -0.861849 -2.104569 -0.494929 1.071804 2000-01-04 0.721555 -0.706771 -1.039575 0.271860 2000-01-05 -0.424972 0.567020 0.276232 -1.087401 2000-01-06 -0.673690 0.113648 -1.478427 0.524988 2000-01-07 0.404705 0.577046 -1.715002 -1.039268 2000-01-08 -0.370647 -1.157892 -1.344312 0.844885
注意
除非特别说明,否则索引功能都不是特定于时间序列的。
因此,根据上述,我们可以使用[]
进行最基本的索引:
In [4]: s = df['A'] In [5]: s[dates[5]] Out[5]: -0.6736897080883706
您可以传递一个列列表给[]
以按顺序选择列。如果 DataFrame 中不包含某列,将引发异常。也可以以这种方式设置多个列:
In [6]: df Out[6]: A B C D 2000-01-01 0.469112 -0.282863 -1.509059 -1.135632 2000-01-02 1.212112 -0.173215 0.119209 -1.044236 2000-01-03 -0.861849 -2.104569 -0.494929 1.071804 2000-01-04 0.721555 -0.706771 -1.039575 0.271860 2000-01-05 -0.424972 0.567020 0.276232 -1.087401 2000-01-06 -0.673690 0.113648 -1.478427 0.524988 2000-01-07 0.404705 0.577046 -1.715002 -1.039268 2000-01-08 -0.370647 -1.157892 -1.344312 0.844885 In [7]: df[['B', 'A']] = df[['A', 'B']] In [8]: df Out[8]: A B C D 2000-01-01 -0.282863 0.469112 -1.509059 -1.135632 2000-01-02 -0.173215 1.212112 0.119209 -1.044236 2000-01-03 -2.104569 -0.861849 -0.494929 1.071804 2000-01-04 -0.706771 0.721555 -1.039575 0.271860 2000-01-05 0.567020 -0.424972 0.276232 -1.087401 2000-01-06 0.113648 -0.673690 -1.478427 0.524988 2000-01-07 0.577046 0.404705 -1.715002 -1.039268 2000-01-08 -1.157892 -0.370647 -1.344312 0.844885
您可能会发现这对于对一部分列应用变换(就地)很有用。
警告
当使用.loc
设置Series
和DataFrame
时,pandas 会对齐所有轴。
这不会修改df
,因为列对齐是在赋值之前进行的。
In [9]: df[['A', 'B']] Out[9]: A B 2000-01-01 -0.282863 0.469112 2000-01-02 -0.173215 1.212112 2000-01-03 -2.104569 -0.861849 2000-01-04 -0.706771 0.721555 2000-01-05 0.567020 -0.424972 2000-01-06 0.113648 -0.673690 2000-01-07 0.577046 0.404705 2000-01-08 -1.157892 -0.370647 In [10]: df.loc[:, ['B', 'A']] = df[['A', 'B']] In [11]: df[['A', 'B']] Out[11]: A B 2000-01-01 -0.282863 0.469112 2000-01-02 -0.173215 1.212112 2000-01-03 -2.104569 -0.861849 2000-01-04 -0.706771 0.721555 2000-01-05 0.567020 -0.424972 2000-01-06 0.113648 -0.673690 2000-01-07 0.577046 0.404705 2000-01-08 -1.157892 -0.370647
交换列值的正确方式是使用原始值:
In [12]: df.loc[:, ['B', 'A']] = df[['A', 'B']].to_numpy() In [13]: df[['A', 'B']] Out[13]: A B 2000-01-01 0.469112 -0.282863 2000-01-02 1.212112 -0.173215 2000-01-03 -0.861849 -2.104569 2000-01-04 0.721555 -0.706771 2000-01-05 -0.424972 0.567020 2000-01-06 -0.673690 0.113648 2000-01-07 0.404705 0.577046 2000-01-08 -0.370647 -1.157892
然而,当使用.iloc
设置Series
和DataFrame
时,pandas 不会对轴进行对齐,因为.iloc
是按位置操作的。
这将修改df
,因为在值分配之前未执行列对齐。
In [14]: df[['A', 'B']] Out[14]: A B 2000-01-01 0.469112 -0.282863 2000-01-02 1.212112 -0.173215 2000-01-03 -0.861849 -2.104569 2000-01-04 0.721555 -0.706771 2000-01-05 -0.424972 0.567020 2000-01-06 -0.673690 0.113648 2000-01-07 0.404705 0.577046 2000-01-08 -0.370647 -1.157892 In [15]: df.iloc[:, [1, 0]] = df[['A', 'B']] In [16]: df[['A','B']] Out[16]: A B 2000-01-01 -0.282863 0.469112 2000-01-02 -0.173215 1.212112 2000-01-03 -2.104569 -0.861849 2000-01-04 -0.706771 0.721555 2000-01-05 0.567020 -0.424972 2000-01-06 0.113648 -0.673690 2000-01-07 0.577046 0.404705 2000-01-08 -1.157892 -0.370647
属性访问
您可以直接访问Series
上的索引或DataFrame
上的列作为属性:
In [17]: sa = pd.Series([1, 2, 3], index=list('abc')) In [18]: dfa = df.copy()
In [19]: sa.b Out[19]: 2 In [20]: dfa.A Out[20]: 2000-01-01 -0.282863 2000-01-02 -0.173215 2000-01-03 -2.104569 2000-01-04 -0.706771 2000-01-05 0.567020 2000-01-06 0.113648 2000-01-07 0.577046 2000-01-08 -1.157892 Freq: D, Name: A, dtype: float64
In [21]: sa.a = 5 In [22]: sa Out[22]: a 5 b 2 c 3 dtype: int64 In [23]: dfa.A = list(range(len(dfa.index))) # ok if A already exists In [24]: dfa Out[24]: A B C D 2000-01-01 0 0.469112 -1.509059 -1.135632 2000-01-02 1 1.212112 0.119209 -1.044236 2000-01-03 2 -0.861849 -0.494929 1.071804 2000-01-04 3 0.721555 -1.039575 0.271860 2000-01-05 4 -0.424972 0.276232 -1.087401 2000-01-06 5 -0.673690 -1.478427 0.524988 2000-01-07 6 0.404705 -1.715002 -1.039268 2000-01-08 7 -0.370647 -1.344312 0.844885 In [25]: dfa['A'] = list(range(len(dfa.index))) # use this form to create a new column In [26]: dfa Out[26]: A B C D 2000-01-01 0 0.469112 -1.509059 -1.135632 2000-01-02 1 1.212112 0.119209 -1.044236 2000-01-03 2 -0.861849 -0.494929 1.071804 2000-01-04 3 0.721555 -1.039575 0.271860 2000-01-05 4 -0.424972 0.276232 -1.087401 2000-01-06 5 -0.673690 -1.478427 0.524988 2000-01-07 6 0.404705 -1.715002 -1.039268 2000-01-08 7 -0.370647 -1.344312 0.844885
警告
- 只有当索引元素是有效的 Python 标识符时,才能使用此访问,例如
s.1
是不允许的。请参阅此处以获取有效标识符的解释。 - 如果属性与现有方法名称冲突,则该属性将不可用,例如
s.min
是不允许的,但s['min']
是可能的。 - 类似地,如果属性与以下列表中的任何一个冲突,则该属性将不可用:
index
,major_axis
,minor_axis
,items
。 - 在任何这些情况下,标准索引仍然有效,例如
s['1']
,s['min']
和s['index']
将访问相应的元素或列。
如果您在 IPython 环境中使用,还可以使用制表符补全来查看这些可访问的属性。
您还可以将dict
分配给DataFrame
的一行:
In [27]: x = pd.DataFrame({'x': [1, 2, 3], 'y': [3, 4, 5]}) In [28]: x.iloc[1] = {'x': 9, 'y': 99} In [29]: x Out[29]: x y 0 1 3 1 9 99 2 3 5
您可以使用属性访问来修改 Series 的现有元素或 DataFrame 的列,但要小心;如果尝试使用属性访问创建新列,则会创建一个新属性而不是新列,并且会引发UserWarning
:
In [30]: df_new = pd.DataFrame({'one': [1., 2., 3.]}) In [31]: df_new.two = [4, 5, 6] In [32]: df_new Out[32]: one 0 1.0 1 2.0 2 3.0
切片范围
沿着任意轴切片范围的最稳健和一致的方法在按位置选择部分详细描述了.iloc
方法。现在,我们解释使用[]
运算符进行切片的语义。
对于 Series,语法与 ndarray 完全相同,返回值的切片和相应的标签:
In [33]: s[:5] Out[33]: 2000-01-01 0.469112 2000-01-02 1.212112 2000-01-03 -0.861849 2000-01-04 0.721555 2000-01-05 -0.424972 Freq: D, Name: A, dtype: float64 In [34]: s[::2] Out[34]: 2000-01-01 0.469112 2000-01-03 -0.861849 2000-01-05 -0.424972 2000-01-07 0.404705 Freq: 2D, Name: A, dtype: float64 In [35]: s[::-1] Out[35]: 2000-01-08 -0.370647 2000-01-07 0.404705 2000-01-06 -0.673690 2000-01-05 -0.424972 2000-01-04 0.721555 2000-01-03 -0.861849 2000-01-02 1.212112 2000-01-01 0.469112 Freq: -1D, Name: A, dtype: float64
请注意,设置也有效:
In [36]: s2 = s.copy() In [37]: s2[:5] = 0 In [38]: s2 Out[38]: 2000-01-01 0.000000 2000-01-02 0.000000 2000-01-03 0.000000 2000-01-04 0.000000 2000-01-05 0.000000 2000-01-06 -0.673690 2000-01-07 0.404705 2000-01-08 -0.370647 Freq: D, Name: A, dtype: float64
对于 DataFrame,在[]
内部切片切片行。这在很大程度上是为了方便,因为这是一个常见的操作。
In [39]: df[:3] Out[39]: A B C D 2000-01-01 -0.282863 0.469112 -1.509059 -1.135632 2000-01-02 -0.173215 1.212112 0.119209 -1.044236 2000-01-03 -2.104569 -0.861849 -0.494929 1.071804 In [40]: df[::-1] Out[40]: A B C D 2000-01-08 -1.157892 -0.370647 -1.344312 0.844885 2000-01-07 0.577046 0.404705 -1.715002 -1.039268 2000-01-06 0.113648 -0.673690 -1.478427 0.524988 2000-01-05 0.567020 -0.424972 0.276232 -1.087401 2000-01-04 -0.706771 0.721555 -1.039575 0.271860 2000-01-03 -2.104569 -0.861849 -0.494929 1.071804 2000-01-02 -0.173215 1.212112 0.119209 -1.044236 2000-01-01 -0.282863 0.469112 -1.509059 -1.135632
Pandas 2.2 中文官方教程和指南(十一·一)(2)https://developer.aliyun.com/article/1509861