美文网首页Python
Python 数据处理(九)—— 重置索引标签

Python 数据处理(九)—— 重置索引标签

作者: 名本无名 | 来源:发表于2021-02-10 10:56 被阅读0次

    7. 重置索引和更改标签

    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,但是这种是不是的调用会拖慢运行速度。

    7.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
    
    7.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)
    
    7.3 重建索引时 NaN 的填充方式

    reindex() 接受一个可选参数 method,用于指定产生缺失值时的填充方法

    image.png

    来看一个简单的例子

    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
    

    这些方法要求索引按递增或递减顺序排列

    注意,使用 fillnainterpolate 可以实现相同的效果(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() 不会对索引的顺序进行任何检查

    7.4 对重建索引的填充方式的限制

    limittolerance 参数可以对 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
    

    注意:当索引为 DatetimeIndexTimedeltaIndexPeriodIndex 时,tolerance 会尽可能将这些索引强制转换为 Timedelta 类型,

    因此需要你为 tolerance 参数设置恰当的字符串。

    7.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
    
    7.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
    

    如果传递的是函数,则该函数必须返回一个值(并且必须生成一组唯一的值)。

    此外,也可以使用 dictSeries

    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() 方法还提供了一个默认为 Falseinplace 参数,并复制一份数据。

    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
    

    相关文章

      网友评论

        本文标题:Python 数据处理(九)—— 重置索引标签

        本文链接:https://www.haomeiwen.com/subject/csdcxltx.html