pandas重置索引标签的实现示例
作者:名本无名
reindex()
是 pandas
里最基本的数据对齐方法,该方法执行标签对齐功能。
reindex
指的是让指定轴上的数据与给定的一组标签进行匹配,能够完成了以下几项操作:
- 将现有数据重新排序,以匹配新的标签集
- 在没有匹配到标签的数据位置插入缺失值(
NaN
)标记 - 可以指定
fill_value
来填充无标签的数据,该操作多见于时间序列数据
例如下面这个例子
In [205]: s = pd.Series(np.random.randn(5), index=["a", "b", "c", "d", "e"]) In [206]: s Out[206]: a 1.695148 b 1.328614 c 1.234686 d -0.385845 e -1.326508 dtype: float64 In [207]: s.reindex(["e", "b", "f", "d"]) Out[207]: e -1.326508 b 1.328614 f NaN d -0.385845 dtype: float64
在这里,标签 f
不包含在 Series
对象中,因此在结果中显示为 NaN
。
对于 DataFrame
对象,您可以重新建立索引和列名
In [208]: df Out[208]: one two three a 1.394981 1.772517 NaN b 0.343054 1.912123 -0.050390 c 0.695246 1.478369 1.227435 d NaN 0.279344 -0.613172 In [209]: df.reindex(index=["c", "f", "b"], columns=["three", "two", "one"]) Out[209]: three two one c 1.227435 1.478369 0.695246 f NaN NaN NaN b -0.050390 1.912123 0.343054
您也可以使用 axis
参数
In [210]: df.reindex(["c", "f", "b"], axis="index") Out[210]: one two three c 0.695246 1.478369 1.227435 f NaN NaN NaN b 0.343054 1.912123 -0.050390
注意,轴标签的索引可以在对象之间共享。
因此,如果我们有一个 Series
和一个 DataFrame
,可以执行以下操作
In [211]: rs = s.reindex(df.index) In [212]: rs Out[212]: a 1.695148 b 1.328614 c 1.234686 d -0.385845 dtype: float64 In [213]: rs.index is df.index Out[213]: True
这意味着重建后的 Series
的索引与 DataFrame
的索引是同一个 Python
对象
DataFrame.reindex()
还支持 “轴样式” 调用,可以指定单个 labels
参数,并指定应用于哪个 axis
。
In [214]: df.reindex(["c", "f", "b"], axis="index") Out[214]: one two three c 0.695246 1.478369 1.227435 f NaN NaN NaN b 0.343054 1.912123 -0.050390 In [215]: df.reindex(["three", "two", "one"], axis="columns") Out[215]: three two one a NaN 1.772517 1.394981 b -0.050390 1.912123 0.343054 c 1.227435 1.478369 0.695246 d -0.613172 0.279344 NaN
在后面的多级索引和高级索引方式中我们将会介绍更加简便的重置索引方式
注意:如果编写的代码对性能要求较高的话,预先对齐的数据操作会更快。例如,对两个未对齐的 DataFrame
相加后台也会先调用 reindex
,但是这种是不是的调用会拖慢运行速度。
1 重建索引并与另一个对象对齐
您可能有时会希望获取一个对象并为其轴重建索引,使其与另一个对象相同。
尽管其语法很简单,但略显冗长,因此 reindex_like()
方法可用于简化此操作
In [216]: df Out[216]: one two a 0.509335 0.840612 b 0.086555 0.523010 c 0.588121 0.351784 d 0.121684 0.027703 In [217]: df2 Out[217]: one two a 0.700215 0.112092 b 0.098034 0.791992 d 0.251426 0.770680 In [218]: df.reindex_like(df2) Out[218]: one two a 0.509335 0.840612 b 0.086555 0.523010 d 0.121684 0.027703
2 用 align 对齐对象
align()
方法是同时对齐两个对象的最快方法,它还支持 join
参数(与连接和合并相关)
join='outer'
: 使用两个索引的并集,默认方式join='left'
: 使用左侧对象的索引join='right'
: 使用右侧对象的索引join='inner'
: 使用两个索引的交集
对于 Series
,它返回一个带有两个重置索引的 Series
的元组
In [219]: s = pd.Series(np.random.randn(5), index=["a", "b", "c", "d", "e"]) In [220]: s1 = s[:4] In [221]: s2 = s[1:] In [222]: s1.align(s2) Out[222]: (a -0.186646 b -1.692424 c -0.303893 d -1.425662 e NaN dtype: float64, a NaN b -1.692424 c -0.303893 d -1.425662 e 1.114285 dtype: float64) In [223]: s1.align(s2, join="inner") Out[223]: (b -1.692424 c -0.303893 d -1.425662 dtype: float64, b -1.692424 c -0.303893 d -1.425662 dtype: float64) In [224]: s1.align(s2, join="left") Out[224]: (a -0.186646 b -1.692424 c -0.303893 d -1.425662 dtype: float64, a NaN b -1.692424 c -0.303893 d -1.425662 dtype: float64)
对于 DataFrame
,连接方法默认同时应用于索引和列
In [225]: df.align(df2, join="inner") Out[225]: ( one two a 1.394981 1.772517 b 0.343054 1.912123 c 0.695246 1.478369, one two a 1.394981 1.772517 b 0.343054 1.912123 c 0.695246 1.478369)
你也可以设置 axis
参数,只在指定的轴上对齐
In [226]: df.align(df2, join="inner", axis=0) Out[226]: ( one two three a 1.394981 1.772517 NaN b 0.343054 1.912123 -0.050390 c 0.695246 1.478369 1.227435, one two a 1.394981 1.772517 b 0.343054 1.912123 c 0.695246 1.478369)
如果将 Series
传递给 DataFrame.align()
,则可以使用 axis
参数指定在 DataFrame
的索引或列上对齐两个对象
In [227]: df.align(df2.iloc[0], axis=1) Out[227]: ( one three two a 1.394981 NaN 1.772517 b 0.343054 -0.050390 1.912123 c 0.695246 1.227435 1.478369 d NaN -0.613172 0.279344, one 1.394981 three NaN two 1.772517 Name: a, dtype: float64)
3 重建索引时 NaN 的填充方式
reindex()
接受一个可选参数 method
,用于指定产生缺失值时的填充方法
来看一个简单的例子
In [228]: rng = pd.date_range("1/3/2000", periods=8) In [229]: ts = pd.Series(np.random.randn(8), index=rng) In [230]: ts2 = ts[[0, 3, 6]] In [231]: ts Out[231]: 2000-01-03 0.183051 2000-01-04 0.400528 2000-01-05 -0.015083 2000-01-06 2.395489 2000-01-07 1.414806 2000-01-08 0.118428 2000-01-09 0.733639 2000-01-10 -0.936077 Freq: D, dtype: float64 In [232]: ts2 Out[232]: 2000-01-03 0.183051 2000-01-06 2.395489 2000-01-09 0.733639 Freq: 3D, dtype: float64 In [233]: ts2.reindex(ts.index) Out[233]: 2000-01-03 0.183051 2000-01-04 NaN 2000-01-05 NaN 2000-01-06 2.395489 2000-01-07 NaN 2000-01-08 NaN 2000-01-09 0.733639 2000-01-10 NaN Freq: D, dtype: float64 In [234]: ts2.reindex(ts.index, method="ffill") Out[234]: 2000-01-03 0.183051 2000-01-04 0.183051 2000-01-05 0.183051 2000-01-06 2.395489 2000-01-07 2.395489 2000-01-08 2.395489 2000-01-09 0.733639 2000-01-10 0.733639 Freq: D, dtype: float64 In [235]: ts2.reindex(ts.index, method="bfill") Out[235]: 2000-01-03 0.183051 2000-01-04 2.395489 2000-01-05 2.395489 2000-01-06 2.395489 2000-01-07 0.733639 2000-01-08 0.733639 2000-01-09 0.733639 2000-01-10 NaN Freq: D, dtype: float64 In [236]: ts2.reindex(ts.index, method="nearest") Out[236]: 2000-01-03 0.183051 2000-01-04 0.183051 2000-01-05 2.395489 2000-01-06 2.395489 2000-01-07 2.395489 2000-01-08 0.733639 2000-01-09 0.733639 2000-01-10 0.733639 Freq: D, dtype: float64
这些方法要求索引按递增或递减顺序排列
注意,使用 fillna
或 interpolate
可以实现相同的效果(method ='nearest'
除外)
In [237]: ts2.reindex(ts.index).fillna(method="ffill") Out[237]: 2000-01-03 0.183051 2000-01-04 0.183051 2000-01-05 0.183051 2000-01-06 2.395489 2000-01-07 2.395489 2000-01-08 2.395489 2000-01-09 0.733639 2000-01-10 0.733639 Freq: D, dtype: float64
如果索引不是单调递增或递减的,reindex()
将引发 ValueError
。而 fillna()
和 interpolate()
不会对索引的顺序进行任何检查
4 对重建索引的填充方式的限制
limit
和 tolerance
参数可以对 reindex
的填充操作进行额外的控制。
limit
限定了连续匹配的最大数量
In [238]: ts2.reindex(ts.index, method="ffill", limit=1) Out[238]: 2000-01-03 0.183051 2000-01-04 0.183051 2000-01-05 NaN 2000-01-06 2.395489 2000-01-07 2.395489 2000-01-08 NaN 2000-01-09 0.733639 2000-01-10 0.733639 Freq: D, dtype: float64
而 tolerance
用于指定索引值之间的最大距离
In [239]: ts2.reindex(ts.index, method="ffill", tolerance="1 day") Out[239]: 2000-01-03 0.183051 2000-01-04 0.183051 2000-01-05 NaN 2000-01-06 2.395489 2000-01-07 2.395489 2000-01-08 NaN 2000-01-09 0.733639 2000-01-10 0.733639 Freq: D, dtype: float64
注意:当索引为 DatetimeIndex
、TimedeltaIndex
或 PeriodIndex
时,tolerance
会尽可能将这些索引强制转换为 Timedelta
类型,
因此需要你为 tolerance
参数设置恰当的字符串。
5 删除标签
drop()
函数经常会与 reindex
配合使用,用于删除轴上的一组标签
In [240]: df Out[240]: one two three a 1.394981 1.772517 NaN b 0.343054 1.912123 -0.050390 c 0.695246 1.478369 1.227435 d NaN 0.279344 -0.613172 In [241]: df.drop(["a", "d"], axis=0) Out[241]: one two three b 0.343054 1.912123 -0.050390 c 0.695246 1.478369 1.227435 In [242]: df.drop(["one"], axis=1) Out[242]: two three a 1.772517 NaN b 1.912123 -0.050390 c 1.478369 1.227435 d 0.279344 -0.613172
注意,虽然下面的方法也可以实现,但不太明显也不太干净
In [243]: df.reindex(df.index.difference(["a", "d"])) Out[243]: one two three b 0.343054 1.912123 -0.050390 c 0.695246 1.478369 1.227435
6 标签的重命名与映射
可以使用 rename()
方法,来基于某些映射(字典或 Series
)或任意函数来重新标记轴
In [244]: s Out[244]: a -0.186646 b -1.692424 c -0.303893 d -1.425662 e 1.114285 dtype: float64 In [245]: s.rename(str.upper) Out[245]: A -0.186646 B -1.692424 C -0.303893 D -1.425662 E 1.114285 dtype: float64
如果传递的是函数,则该函数必须返回一个值(并且必须生成一组唯一的值)。
此外,也可以使用 dict
或 Series
In [246]: df.rename( .....: columns={"one": "foo", "two": "bar"}, .....: index={"a": "apple", "b": "banana", "d": "durian"}, .....: ) .....: Out[246]: foo bar three apple 1.394981 1.772517 NaN banana 0.343054 1.912123 -0.050390 c 0.695246 1.478369 1.227435 durian NaN 0.279344 -0.613172
如果传入的映射不包含索引和列名标签,则它不会被重命名。
注意,映射中的多出来的标签不会触发异常
也可以为 axis
指定名称,对相应的轴执行映射操作
In [247]: df.rename({"one": "foo", "two": "bar"}, axis="columns") Out[247]: foo bar three a 1.394981 1.772517 NaN b 0.343054 1.912123 -0.050390 c 0.695246 1.478369 1.227435 d NaN 0.279344 -0.613172 In [248]: df.rename({"a": "apple", "b": "banana", "d": "durian"}, axis="index") Out[248]: one two three apple 1.394981 1.772517 NaN banana 0.343054 1.912123 -0.050390 c 0.695246 1.478369 1.227435 durian NaN 0.279344 -0.613172
rename()
方法还提供了一个默认为 False
的 inplace
参数,并复制一份数据。
当 inplace=True
时,会在原数据上重命名
rename()
还支持使用标量或列表的方式来更改 Series.name
属性
In [249]: s.rename("scalar-name") Out[249]: a -0.186646 b -1.692424 c -0.303893 d -1.425662 e 1.114285 Name: scalar-name, dtype: float64
还可以使用 DataFrame.rename_axis()
和 Series.rename_axis()
方法来更改 MultiIndex
的名称
In [250]: df = pd.DataFrame( .....: {"x": [1, 2, 3, 4, 5, 6], "y": [10, 20, 30, 40, 50, 60]}, .....: index=pd.MultiIndex.from_product( .....: [["a", "b", "c"], [1, 2]], names=["let", "num"] .....: ), .....: ) .....: In [251]: df Out[251]: x y let num a 1 1 10 2 2 20 b 1 3 30 2 4 40 c 1 5 50 2 6 60 In [252]: df.rename_axis(index={"let": "abc"}) Out[252]: x y abc num a 1 1 10 2 2 20 b 1 3 30 2 4 40 c 1 5 50 2 6 60 In [253]: df.rename_axis(index=str.upper) Out[253]: x y LET NUM a 1 1 10 2 2 20 b 1 3 30 2 4 40 c 1 5 50 2 6 60
到此这篇关于pandas重置索引标签的实现示例的文章就介绍到这了,更多相关pandas重置索引标签内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!