【问题标题】:How can I increment a level in Pandas MultiIndex?如何在 Pandas MultiIndex 中增加一个级别?
【发布时间】:2017-04-19 02:47:47
【问题描述】:

如何增加 pandas 多索引特定级别中的所有值?

【问题讨论】:

    标签: pandas multi-index


    【解决方案1】:

    可以这么简单

    df.index.set_levels(df.index.levels[0] + 1, 0, inplace=True)
    

    演示

    df = pd.DataFrame(
        dict(A=[2, 3, 4, 5]),
        pd.MultiIndex.from_product([[1, 2], [3, 4]])
    )
    df
    

    df.index.set_levels(df.index.levels[0] + 1, 0, inplace=True)
    df
    

    【讨论】:

    • TypeError: 'FrozenList' does not support mutable operations.
    【解决方案2】:

    您可以创建新的MultiIndex.from_tuples 并分配:

    df = pd.DataFrame({'A':[1,2,3],
                       'B':[4,5,6],
                       'C':[7,8,9],
                       'D':[1,3,5],
                       'E':[5,3,6],
                       'F':[7,4,3]})
    
    df = df.set_index(['A','B'])
    print (df)
         C  D  E  F
    A B            
    1 4  7  1  5  7
    2 5  8  3  3  4
    3 6  9  5  6  3
    
    #change multiindex
    new_index = list(zip(df.index.get_level_values('A'), df.index.get_level_values('B') + 1))
    df.index = pd.MultiIndex.from_tuples(new_index, names = df.index.names)
    print (df)
         C  D  E  F
    A B            
    1 5  7  1  5  7
    2 6  8  3  3  4
    3 7  9  5  6  3
    

    reset_indexset_index 的另一种可能解决方案:

    df = df.reset_index()
    df.B = df.B + 1
    df = df.set_index(['A','B'])
    print (df)
         C  D  E  F
    A B            
    1 5  7  1  5  7
    2 6  8  3  3  4
    3 7  9  5  6  3
    

    DataFrame.assign 的解决方案:

    print (df.reset_index().assign(B=lambda x: x.B+1).set_index(['A','B']))
    

    时间安排

    In [26]: %timeit (reset_set(df1))
    1 loop, best of 3: 144 ms per loop
    
    In [27]: %timeit (assign_method(df3))
    10 loops, best of 3: 161 ms per loop
    
    In [28]: %timeit (jul(df2))
    1 loop, best of 3: 543 ms per loop
    
    In [29]: %timeit (tuples_method(df))
    1 loop, best of 3: 581 ms per loop
    

    计时码

    np.random.seed(100)
    N = 1000000
    df = pd.DataFrame(np.random.randint(10, size=(N,5)), columns=list('ABCDE'))
    print (df)
    
    df = df.set_index(['A','B'])
    print (df)
    df1 = df.copy()
    df2 = df.copy()
    df3 = df.copy()
    
    def reset_set(df):
        df = df.reset_index()
        df.B = df.B + 1
        return df.set_index(['A','B'])
    
    def assign_method(df):
        df = df.reset_index().assign(B=lambda x: x.B+1).set_index(['A','B']) 
        return df   
    
    def tuples_method(df):
        new_index = list(zip(df.index.get_level_values('A'), df.index.get_level_values('B') + 1))
        df.index = pd.MultiIndex.from_tuples(new_index, names = df.index.names)
        return df
    
    def jul(df):
        df.index = pd.MultiIndex.from_tuples([(x[0], x[1]+1) for x in df.index], names=df.index.names)
        return df
    

    感谢Jeff 提供另一个解决方案:

    df.index.set_levels(df.index.levels[1] + 1 , level=1, inplace=True)
    print (df)
    
         C  D  E  F
    A B            
    1 5  7  1  5  7
    2 6  8  3  3  4
    3 7  9  5  6  3
    

    【讨论】:

    • 酷,谢谢!我觉得奇怪,这是一个如此繁琐的操作.. :/
    • 不幸的是。
    • 我猜有一些性能实现细节可以做到这一点?
    • 我先瘦第二快,但我可以添加计时
    • pandas.pydata.org/pandas-docs/stable/generated/… 是惯用的方式;也将是迄今为止性能最高的,因为您只设置了实际级别
    【解决方案3】:

    这里有一个稍微不同的方式:

    df.index = pd.MultiIndex.from_tuples([(x[0], x[1]+1) for x in df.index], names=df.index.names)
    
    1000 loops, best of 3: 840 µs per loop
    

    比较:

    new_index = list(zip(df.index.get_level_values('A'), 
    df.index.get_level_values('B') + 1))
    df.index = pd.MultiIndex.from_tuples(new_index, names = df.index.names)
    
    1000 loops, best of 3: 984 µs per loop
    

    reset_index 方法慢了 10 倍。

    【讨论】:

      猜你喜欢
      • 2020-09-16
      • 2013-01-22
      • 2022-01-08
      • 2019-02-16
      • 1970-01-01
      • 2018-11-09
      • 2017-06-18
      • 2016-03-12
      • 2020-02-14
      相关资源
      最近更新 更多