Pandas 2.2 中文官方教程和指南(九·三)(1)https://developer.aliyun.com/article/1509732
items
与类似字典的接口一致,items()
遍历键值对:
- Series:(索引,标量值)对
- DataFrame:(列,Series)对
例如:
In [258]: for label, ser in df.items(): .....: print(label) .....: print(ser) .....: a 0 1 1 2 2 3 Name: a, dtype: int64 b 0 a 1 b 2 c Name: b, dtype: object
iterrows
iterrows()
允许您将 DataFrame 的行作为 Series 对象进行迭代。它返回一个迭代器,产生每个索引值以及包含每行数据的 Series:
In [259]: for row_index, row in df.iterrows(): .....: print(row_index, row, sep="\n") .....: 0 a 1 b a Name: 0, dtype: object 1 a 2 b b Name: 1, dtype: object 2 a 3 b c Name: 2, dtype: object
注意
因为iterrows()
为每行返回一个 Series,它不会在行之间保留数据类型(数据类型在 DataFrame 的列之间保留)。例如,
In [260]: df_orig = pd.DataFrame([[1, 1.5]], columns=["int", "float"]) In [261]: df_orig.dtypes Out[261]: int int64 float float64 dtype: object In [262]: row = next(df_orig.iterrows())[1] In [263]: row Out[263]: int 1.0 float 1.5 Name: 0, dtype: float64
row
中的所有值,作为一个 Series 返回,现在都被转换为浮点数,包括列x
中的原始整数值:
In [264]: row["int"].dtype Out[264]: dtype('float64') In [265]: df_orig["int"].dtype Out[265]: dtype('int64')
为了在迭代行时保留数据类型,最好使用itertuples()
,它返回值的命名元组,通常比iterrows()
快得多。
例如,转置 DataFrame 的一种构造方法是:
In [266]: df2 = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]}) In [267]: print(df2) x y 0 1 4 1 2 5 2 3 6 In [268]: print(df2.T) 0 1 2 x 1 2 3 y 4 5 6 In [269]: df2_t = pd.DataFrame({idx: values for idx, values in df2.iterrows()}) In [270]: print(df2_t) 0 1 2 x 1 2 3 y 4 5 6
itertuples
itertuples()
方法将返回一个迭代器,为 DataFrame 中的每一行生成一个命名元组。元组的第一个元素将是行的相应索引值,而其余值是行值。
例如:
In [271]: for row in df.itertuples(): .....: print(row) .....: Pandas(Index=0, a=1, b='a') Pandas(Index=1, a=2, b='b') Pandas(Index=2, a=3, b='c')
此方法不会将行转换为 Series 对象;它仅返回命名元组中的值。因此,itertuples()
保留值的数据类型,并且通常比iterrows()
快得多。
注意
如果列名是无效的 Python 标识符、重复的或以下划线开头,则列名将重命名为位置名称。如果列数较多(>255),则返回常规元组。
项目
与类似字典的接口一致,items()
迭代遍历键值对:
- Series:(索引,标量值) 对
- DataFrame:(列,Series) 对
例如:
In [258]: for label, ser in df.items(): .....: print(label) .....: print(ser) .....: a 0 1 1 2 2 3 Name: a, dtype: int64 b 0 a 1 b 2 c Name: b, dtype: object
遍历行
iterrows()
允许您遍历 DataFrame 的行作为 Series 对象。它返回一个迭代器,每个索引值以及包含每行数据的 Series:
In [259]: for row_index, row in df.iterrows(): .....: print(row_index, row, sep="\n") .....: 0 a 1 b a Name: 0, dtype: object 1 a 2 b b Name: 1, dtype: object 2 a 3 b c Name: 2, dtype: object
注意
因为iterrows()
为每行返回一个 Series,它不会在行之间保留 dtype(对于 DataFrame,dtype 在列之间保留)。例如,
In [260]: df_orig = pd.DataFrame([[1, 1.5]], columns=["int", "float"]) In [261]: df_orig.dtypes Out[261]: int int64 float float64 dtype: object In [262]: row = next(df_orig.iterrows())[1] In [263]: row Out[263]: int 1.0 float 1.5 Name: 0, dtype: float64
返回为 Series 的row
中的所有值现在都被转换为浮点数,包括列x
中的原始整数值:
In [264]: row["int"].dtype Out[264]: dtype('float64') In [265]: df_orig["int"].dtype Out[265]: dtype('int64')
在遍历行时保留 dtypes,最好使用itertuples()
,它返回值的命名元组,通常比iterrows()
快得多。
例如,转置 DataFrame 的一种构造方法是:
In [266]: df2 = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]}) In [267]: print(df2) x y 0 1 4 1 2 5 2 3 6 In [268]: print(df2.T) 0 1 2 x 1 2 3 y 4 5 6 In [269]: df2_t = pd.DataFrame({idx: values for idx, values in df2.iterrows()}) In [270]: print(df2_t) 0 1 2 x 1 2 3 y 4 5 6
itertuples
itertuples()
方法将返回一个迭代器,为 DataFrame 中的每一行生成一个命名元组。元组的第一个元素将是行的相应索引值,而其余值是行值。
例如:
In [271]: for row in df.itertuples(): .....: print(row) .....: Pandas(Index=0, a=1, b='a') Pandas(Index=1, a=2, b='b') Pandas(Index=2, a=3, b='c')
此方法不会将行转换为 Series
对象;它只是返回命名元组内的值。因此,itertuples()
保留了值的数据类型,并且通常比 iterrows()
更快。
注意
如果列名无效的 Python 标识符、重复或以下划线开头,则列名将重命名为位置名称。当列数较多(>255)时,将返回常规元组。
.dt 访问器
如果 Series
是日期时间/周期类别的 Series
,则 Series
具有一种访问器,以简洁地返回 Series
的值的日期时间类属性。这将返回一个 Series
,其索引类似于现有的 Series
。
# datetime In [272]: s = pd.Series(pd.date_range("20130101 09:10:12", periods=4)) In [273]: s Out[273]: 0 2013-01-01 09:10:12 1 2013-01-02 09:10:12 2 2013-01-03 09:10:12 3 2013-01-04 09:10:12 dtype: datetime64[ns] In [274]: s.dt.hour Out[274]: 0 9 1 9 2 9 3 9 dtype: int32 In [275]: s.dt.second Out[275]: 0 12 1 12 2 12 3 12 dtype: int32 In [276]: s.dt.day Out[276]: 0 1 1 2 2 3 3 4 dtype: int32
这使得可以像这样进行美观的表达:
In [277]: s[s.dt.day == 2] Out[277]: 1 2013-01-02 09:10:12 dtype: datetime64[ns]
您可以轻松地生成带时区的转换:
In [278]: stz = s.dt.tz_localize("US/Eastern") In [279]: stz Out[279]: 0 2013-01-01 09:10:12-05:00 1 2013-01-02 09:10:12-05:00 2 2013-01-03 09:10:12-05:00 3 2013-01-04 09:10:12-05:00 dtype: datetime64[ns, US/Eastern] In [280]: stz.dt.tz Out[280]: <DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>
您还可以链接这些类型的操作:
In [281]: s.dt.tz_localize("UTC").dt.tz_convert("US/Eastern") Out[281]: 0 2013-01-01 04:10:12-05:00 1 2013-01-02 04:10:12-05:00 2 2013-01-03 04:10:12-05:00 3 2013-01-04 04:10:12-05:00 dtype: datetime64[ns, US/Eastern]
您还可以使用 Series.dt.strftime()
将日期时间值格式化为字符串,其支持与标准 strftime()
相同的格式。
# DatetimeIndex In [282]: s = pd.Series(pd.date_range("20130101", periods=4)) In [283]: s Out[283]: 0 2013-01-01 1 2013-01-02 2 2013-01-03 3 2013-01-04 dtype: datetime64[ns] In [284]: s.dt.strftime("%Y/%m/%d") Out[284]: 0 2013/01/01 1 2013/01/02 2 2013/01/03 3 2013/01/04 dtype: object
# PeriodIndex In [285]: s = pd.Series(pd.period_range("20130101", periods=4)) In [286]: s Out[286]: 0 2013-01-01 1 2013-01-02 2 2013-01-03 3 2013-01-04 dtype: period[D] In [287]: s.dt.strftime("%Y/%m/%d") Out[287]: 0 2013/01/01 1 2013/01/02 2 2013/01/03 3 2013/01/04 dtype: object
.dt
访问器适用于周期和时间增量数据类型。
# period In [288]: s = pd.Series(pd.period_range("20130101", periods=4, freq="D")) In [289]: s Out[289]: 0 2013-01-01 1 2013-01-02 2 2013-01-03 3 2013-01-04 dtype: period[D] In [290]: s.dt.year Out[290]: 0 2013 1 2013 2 2013 3 2013 dtype: int64 In [291]: s.dt.day Out[291]: 0 1 1 2 2 3 3 4 dtype: int64
# timedelta In [292]: s = pd.Series(pd.timedelta_range("1 day 00:00:05", periods=4, freq="s")) In [293]: s Out[293]: 0 1 days 00:00:05 1 1 days 00:00:06 2 1 days 00:00:07 3 1 days 00:00:08 dtype: timedelta64[ns] In [294]: s.dt.days Out[294]: 0 1 1 1 2 1 3 1 dtype: int64 In [295]: s.dt.seconds Out[295]: 0 5 1 6 2 7 3 8 dtype: int32 In [296]: s.dt.components Out[296]: days hours minutes seconds milliseconds microseconds nanoseconds 0 1 0 0 5 0 0 0 1 1 0 0 6 0 0 0 2 1 0 0 7 0 0 0 3 1 0 0 8 0 0 0
注意
如果您使用非日期时间类似值访问 Series.dt
,将引发 TypeError
。
向量化字符串方法
Series
配备了一组字符串处理方法,使得操作数组的每个元素变得容易。最重要的是,这些方法会自动排除丢失/NA 值。通过 Series
的 str
属性访问这些方法,通常名称与等效的(标量)内置字符串方法匹配。例如:
In [297]: s = pd.Series( .....: ["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string" .....: ) .....: In [298]: s.str.lower() Out[298]: 0 a 1 b 2 c 3 aaba 4 baca 5 <NA> 6 caba 7 dog 8 cat dtype: string
还提供了强大的模式匹配方法,但请注意,模式匹配通常默认使用正则表达式(有些情况下总是使用)。
注意
在 pandas 1.0 之前,字符串方法仅适用于 object
-dtype Series
。pandas 1.0 添加了 StringDtype
,专门用于字符串。有关更多信息,请参阅文本数据类型。
请参阅向量化字符串方法以获取完整的描述。
排序
pandas 支持三种排序方式:按索引标签排序、按列值排序以及按两者组合排序。
按索引
Series.sort_index()
和 DataFrame.sort_index()
方法用于按索引级别对 pandas 对象进行排序。
In [299]: df = pd.DataFrame( .....: { .....: "one": pd.Series(np.random.randn(3), index=["a", "b", "c"]), .....: "two": pd.Series(np.random.randn(4), index=["a", "b", "c", "d"]), .....: "three": pd.Series(np.random.randn(3), index=["b", "c", "d"]), .....: } .....: ) .....: In [300]: unsorted_df = df.reindex( .....: index=["a", "d", "c", "b"], columns=["three", "two", "one"] .....: ) .....: In [301]: unsorted_df Out[301]: three two one a NaN -1.152244 0.562973 d -0.252916 -0.109597 NaN c 1.273388 -0.167123 0.640382 b -0.098217 0.009797 -1.299504 # DataFrame In [302]: unsorted_df.sort_index() Out[302]: three two one a NaN -1.152244 0.562973 b -0.098217 0.009797 -1.299504 c 1.273388 -0.167123 0.640382 d -0.252916 -0.109597 NaN In [303]: unsorted_df.sort_index(ascending=False) Out[303]: three two one d -0.252916 -0.109597 NaN c 1.273388 -0.167123 0.640382 b -0.098217 0.009797 -1.299504 a NaN -1.152244 0.562973 In [304]: unsorted_df.sort_index(axis=1) Out[304]: one three two a 0.562973 NaN -1.152244 d NaN -0.252916 -0.109597 c 0.640382 1.273388 -0.167123 b -1.299504 -0.098217 0.009797 # Series In [305]: unsorted_df["three"].sort_index() Out[305]: a NaN b -0.098217 c 1.273388 d -0.252916 Name: three, dtype: float64
按索引排序还支持一个 key
参数,该参数接受一个可调用函数,应用于正在排序的索引。对于 MultiIndex
对象,key 会按级别应用到由 level
指定的级别。
In [306]: s1 = pd.DataFrame({"a": ["B", "a", "C"], "b": [1, 2, 3], "c": [2, 3, 4]}).set_index( .....: list("ab") .....: ) .....: In [307]: s1 Out[307]: c a b B 1 2 a 2 3 C 3 4
In [308]: s1.sort_index(level="a") Out[308]: c a b B 1 2 C 3 4 a 2 3 In [309]: s1.sort_index(level="a", key=lambda idx: idx.str.lower()) Out[309]: c a b a 2 3 B 1 2 C 3 4
有关按值排序的关键信息,请参见 value sorting。 ### 按值排序
Series.sort_values()
方法用于按其值对 Series
进行排序。DataFrame.sort_values()
方法用于按其列或行值对 DataFrame
进行排序。可选的 by
参数可用于指定一个或多个列以确定排序顺序。
In [310]: df1 = pd.DataFrame( .....: {"one": [2, 1, 1, 1], "two": [1, 3, 2, 4], "three": [5, 4, 3, 2]} .....: ) .....: In [311]: df1.sort_values(by="two") Out[311]: one two three 0 2 1 5 2 1 2 3 1 1 3 4 3 1 4 2
by
参数可以接受列名的列表,例如:
In [312]: df1[["one", "two", "three"]].sort_values(by=["one", "two"]) Out[312]: one two three 2 1 2 3 1 1 3 4 3 1 4 2 0 2 1 5
这些方法通过 na_position
参数对 NA 值进行特殊处理:
In [313]: s[2] = np.nan In [314]: s.sort_values() Out[314]: 0 A 3 Aaba 1 B 4 Baca 6 CABA 8 cat 7 dog 2 <NA> 5 <NA> dtype: string In [315]: s.sort_values(na_position="first") Out[315]: 2 <NA> 5 <NA> 0 A 3 Aaba 1 B 4 Baca 6 CABA 8 cat 7 dog dtype: string
排序还支持一个 key
参数,该参数接受一个可调用函数,应用于正在排序的值。
In [316]: s1 = pd.Series(["B", "a", "C"])
In [317]: s1.sort_values() Out[317]: 0 B 2 C 1 a dtype: object In [318]: s1.sort_values(key=lambda x: x.str.lower()) Out[318]: 1 a 0 B 2 C dtype: object
key
将获得值的 Series
并应返回具有相同形状的转换值的 Series
或数组。对于 DataFrame
对象,key 会按列应用,因此 key 仍应期望一个 Series 并返回一个 Series,例如
In [319]: df = pd.DataFrame({"a": ["B", "a", "C"], "b": [1, 2, 3]}) • 1
In [320]: df.sort_values(by="a") Out[320]: a b 0 B 1 2 C 3 1 a 2 In [321]: df.sort_values(by="a", key=lambda col: col.str.lower()) Out[321]: a b 1 a 2 0 B 1 2 C 3
每列的名称或类型可用于对不同列应用不同函数。 ### 按索引和值排序
作为 by
参数传递给 DataFrame.sort_values()
的字符串可以指代列或索引级别名称。
# Build MultiIndex In [322]: idx = pd.MultiIndex.from_tuples( .....: [("a", 1), ("a", 2), ("a", 2), ("b", 2), ("b", 1), ("b", 1)] .....: ) .....: In [323]: idx.names = ["first", "second"] # Build DataFrame In [324]: df_multi = pd.DataFrame({"A": np.arange(6, 0, -1)}, index=idx) In [325]: df_multi Out[325]: A first second a 1 6 2 5 2 4 b 2 3 1 2 1 1
按‘second’(索引)和‘A’(列)排序
In [326]: df_multi.sort_values(by=["second", "A"]) Out[326]: A first second b 1 1 1 2 a 1 6 b 2 3 a 2 4 2 5
注意
如果一个字符串既匹配列名又匹配索引级别名称,则会发出警告并且列优先。这将导致在将来版本中出现歧义错误。 ### searchsorted
Series 有 searchsorted()
方法,其工作方式类似于 numpy.ndarray.searchsorted()
。
In [327]: ser = pd.Series([1, 2, 3]) In [328]: ser.searchsorted([0, 3]) Out[328]: array([0, 2]) In [329]: ser.searchsorted([0, 4]) Out[329]: array([0, 3]) In [330]: ser.searchsorted([1, 3], side="right") Out[330]: array([1, 3]) In [331]: ser.searchsorted([1, 3], side="left") Out[331]: array([0, 2]) In [332]: ser = pd.Series([3, 1, 2]) In [333]: ser.searchsorted([0, 3], sorter=np.argsort(ser)) Out[333]: array([0, 2]) ```### 最小/最大值 `Series` 有 `nsmallest()` 和 `nlargest()` 方法,返回最小或最大的 \(n\) 值。对于大型 `Series`,这比对整个 Series 进行排序并在结果上调用 `head(n)` 要快得多。 ```py In [334]: s = pd.Series(np.random.permutation(10)) In [335]: s Out[335]: 0 2 1 0 2 3 3 7 4 1 5 5 6 9 7 6 8 8 9 4 dtype: int64 In [336]: s.sort_values() Out[336]: 1 0 4 1 0 2 2 3 9 4 5 5 7 6 3 7 8 8 6 9 dtype: int64 In [337]: s.nsmallest(3) Out[337]: 1 0 4 1 0 2 dtype: int64 In [338]: s.nlargest(3) Out[338]: 6 9 8 8 3 7 dtype: int64
DataFrame
也有 nlargest
和 nsmallest
方法。
In [339]: df = pd.DataFrame( .....: { .....: "a": [-2, -1, 1, 10, 8, 11, -1], .....: "b": list("abdceff"), .....: "c": [1.0, 2.0, 4.0, 3.2, np.nan, 3.0, 4.0], .....: } .....: ) .....: In [340]: df.nlargest(3, "a") Out[340]: a b c 5 11 f 3.0 3 10 c 3.2 4 8 e NaN In [341]: df.nlargest(5, ["a", "c"]) Out[341]: a b c 5 11 f 3.0 3 10 c 3.2 4 8 e NaN 2 1 d 4.0 6 -1 f 4.0 In [342]: df.nsmallest(3, "a") Out[342]: a b c 0 -2 a 1.0 1 -1 b 2.0 6 -1 f 4.0 In [343]: df.nsmallest(5, ["a", "c"]) Out[343]: a b c 0 -2 a 1.0 1 -1 b 2.0 6 -1 f 4.0 2 1 d 4.0 4 8 e NaN ```### 按 MultiIndex 列排序 当列是 MultiIndex 时,必须明确指定排序,并完全指定所有级别到 `by`。 ```py In [344]: df1.columns = pd.MultiIndex.from_tuples( .....: [("a", "one"), ("a", "two"), ("b", "three")] .....: ) .....: In [345]: df1.sort_values(by=("a", "two")) Out[345]: a b one two three 0 2 1 5 2 1 2 3 1 1 3 4 3 1 4 2 ```### 按索引 `Series.sort_index()` 和 `DataFrame.sort_index()` 方法用于按其索引级别对 pandas 对象进行排序。 ```py In [299]: df = pd.DataFrame( .....: { .....: "one": pd.Series(np.random.randn(3), index=["a", "b", "c"]), .....: "two": pd.Series(np.random.randn(4), index=["a", "b", "c", "d"]), .....: "three": pd.Series(np.random.randn(3), index=["b", "c", "d"]), .....: } .....: ) .....: In [300]: unsorted_df = df.reindex( .....: index=["a", "d", "c", "b"], columns=["three", "two", "one"] .....: ) .....: In [301]: unsorted_df Out[301]: three two one a NaN -1.152244 0.562973 d -0.252916 -0.109597 NaN c 1.273388 -0.167123 0.640382 b -0.098217 0.009797 -1.299504 # DataFrame In [302]: unsorted_df.sort_index() Out[302]: three two one a NaN -1.152244 0.562973 b -0.098217 0.009797 -1.299504 c 1.273388 -0.167123 0.640382 d -0.252916 -0.109597 NaN In [303]: unsorted_df.sort_index(ascending=False) Out[303]: three two one d -0.252916 -0.109597 NaN c 1.273388 -0.167123 0.640382 b -0.098217 0.009797 -1.299504 a NaN -1.152244 0.562973 In [304]: unsorted_df.sort_index(axis=1) Out[304]: one three two a 0.562973 NaN -1.152244 d NaN -0.252916 -0.109597 c 0.640382 1.273388 -0.167123 b -1.299504 -0.098217 0.009797 # Series In [305]: unsorted_df["three"].sort_index() Out[305]: a NaN b -0.098217 c 1.273388 d -0.252916 Name: three, dtype: float64
按索引排序还支持一个 key
参数,该参数接受一个可调用函数,应用于要排序的索引。对于 MultiIndex
对象,key 会按指定的 level
对每个级别应用。
In [306]: s1 = pd.DataFrame({"a": ["B", "a", "C"], "b": [1, 2, 3], "c": [2, 3, 4]}).set_index( .....: list("ab") .....: ) .....: In [307]: s1 Out[307]: c a b B 1 2 a 2 3 C 3 4
In [308]: s1.sort_index(level="a") Out[308]: c a b B 1 2 C 3 4 a 2 3 In [309]: s1.sort_index(level="a", key=lambda idx: idx.str.lower()) Out[309]: c a b a 2 3 B 1 2 C 3 4
有关按值排序的键排序信息,请参阅 值排序。
Pandas 2.2 中文官方教程和指南(九·三)(3)https://developer.aliyun.com/article/1509732