【问题标题】:dataframe value diagonal shift row数据帧值对角线移位行
【发布时间】:2021-07-06 14:04:47
【问题描述】:

我想对df 中的每一行进行左移,就像对角线移位一样。 我有这样的df:

        a1 a2  a3  a4
row1    1   5   5   3
row2    0   4   1   4
row3    0   0   7   6
row4    0   0   0   2

并希望拥有它:

        a1 a2  a3  a4
row1    1   5   5   3
row2    4   1   4   0
row3    7   6   0   0
row4    2   0   0   0

我的想法是对每一行使用 .shift() 方法取决于数字。但是有没有更好的方法来解决这个任务?

我的解决办法是:

for i in range(0, len(df)):
   df.iloc[i] = df.iloc[i].shift(periods=-i,  fill_value = 0)

【问题讨论】:

    标签: python pandas dataframe shift


    【解决方案1】:

    IIUC,这是一种方法:

    df1 = df.mask(df.eq(0)).apply(lambda x: pd.Series(sorted(x, key=pd.isnull)), axis = 1).fillna(0, downcast='infer')
    df1.columns = df.columns
    

    【讨论】:

    • 谢谢!!肯定会玩你的想法!
    【解决方案2】:

    一种使用fliplr 翻转零值位置的numpy 方法:

    import numpy as np
    import pandas as pd
    
    df = pd.DataFrame({
        'a1': {'row1': 1, 'row2': 0, 'row3': 0, 'row4': 0},
        'a2': {'row1': 5, 'row2': 4, 'row3': 0, 'row4': 0},
        'a3': {'row1': 5, 'row2': 1, 'row3': 7, 'row4': 0},
        'a4': {'row1': 3, 'row2': 4, 'row3': 6, 'row4': 2}
    })
    
    mask = df.ne(0)
    flipped = np.fliplr(mask)
    df.values[flipped] = df.values[mask]
    df.values[~flipped] = 0
    

    df:

          a1  a2  a3  a4
    row1   1   5   5   3
    row2   4   1   4   0
    row3   7   6   0   0
    row4   2   0   0   0
    

    一个类似的方法,除了将所有的 0 移动到末尾而不是仅仅翻转:

    mask = df.ne(0).values
    sorted_mask = np.take_along_axis(mask, np.argsort(~mask), axis=1)
    df.values[sorted_mask] = df.values[mask]
    df.values[~sorted_mask] = 0
    

    修改df

          a1  a2  a3  a4
    row1   1   0   5   3  # 0 added to a2
    row2   0   4   1   4
    row3   0   0   7   6
    row4   0   0   0   2
    

    翻转方法:

          a1  a2  a3  a4
    row1   1   5   0   3  # 0 position has been flipped
    row2   4   1   4   0
    row3   7   6   0   0
    row4   2   0   0   0
    

    排序方法:

          a1  a2  a3  a4
    row1   1   5   3   0  # 0 is at end
    row2   4   1   4   0
    row3   7   6   0   0
    row4   2   0   0   0
    

    翻转方法的分解:

    mask = df.ne(0)
    

    mask 保存非零值的位置:

             a1     a2     a3    a4
    row1   True   True   True  True
    row2  False   True   True  True
    row3  False  False   True  True
    row4  False  False  False  True
    

    flipped 持有掩码,0 翻转到另一侧:

    [[ True  True  True  True]
     [ True  True  True False]
     [ True  True False False]
     [ True False False False]]
    

    df 中的非零值根据翻转被分配回:

    df.values[flipped]  # [1 5 5 3 0 4 1 0 0 0]
    df.values[mask]  # [1 5 5 3 4 1 4 7 6 2]
    
    df.values[flipped] = df.values[mask]
    
          a1  a2  a3  a4
    row1   1   5   5   3
    row2   4   1   4   4
    row3   7   6   7   6
    row4   2   0   0   2
    

    那么旧值需要用零覆盖:

    df.values[~flipped] = 0
    
          a1  a2  a3  a4
    row1   1   5   5   3
    row2   4   1   4   0
    row3   7   6   0   0
    row4   2   0   0   0
    

    排序方法类似,但不是翻转 mask 而是排序:

    mask = df.ne(0).values
    sorted_mask = np.take_along_axis(mask, np.argsort(~mask), axis=1)
    

    df:

          a1  a2  a3  a4
    row1   1   0   5   3
    row2   0   4   1   4
    row3   0   0   7   6
    row4   0   0   0   2
    

    mask:

    [[ True False  True  True]
     [False  True  True  True]
     [False False  True  True]
     [False False False  True]]
    

    sorted_mask:

    [[ True  True  True False]  # Falses are at end of the row always
     [ True  True  True False]
     [ True  True False False]
     [ True False False False]]
    

    【讨论】:

    • 非常感谢您提供如此详细的答案!将根据您的想法工作!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    • 2014-12-23
    • 2014-07-06
    • 2018-09-06
    • 1970-01-01
    • 2019-06-30
    相关资源
    最近更新 更多