代码之家  ›  专栏  ›  技术社区  ›  Nate Thompson

Python-按列保留第一个唯一值

  •  3
  • Nate Thompson  · 技术社区  · 6 年前

    我有一个dataframe,它有多个列来表示某个东西是否存在,但它们本质上是有序的。有些东西可能存在于所有3个类别中,但我只想指出它存在于的最高级别。

    所以对于给定的行,我只需要一个'1'值,但我希望它保持在它所在的最高级别。

    对于此行: 1,1,0 ,我希望将行更改为 1,0,0

    0,1,1 ,我希望将行更改为 0,1,0

    import pandas as pd
    
    #input data
    df = pd.DataFrame({'id':[1,2,3,4,5],
                       'level1':[0,0,0,0,1],
                       'level2':[1,0,1,0,1],
                       'level3':[0,1,1,1,0]})
    
    #expected output:
    new_df = pd.DataFrame({'id':[1,2,3,4,5],
                       'level1':[0,0,0,0,1],
                       'level2':[1,0,1,0,0],
                       'level3':[0,1,0,1,0]})
    
    4 回复  |  直到 6 年前
        1
  •  1
  •   DJK    6 年前

    get_dummies()

    df[df.filter(like='level').columns] = pd.get_dummies(df.filter(like='level').idxmax(1))
    
       id  level1  level2  level3
    0   1       0       1       0
    1   2       0       0       1
    2   3       0       1       0
    3   4       0       0       1
    4   5       1       0       0
    
        2
  •  3
  •   user3483203    6 年前

    使用 numpy.zeros 并通过 numpy.argmax :

    out = np.zeros(df.iloc[:, 1:].shape, dtype=int)
    out[np.arange(len(out)), np.argmax(df.iloc[:, 1:].values, 1)] = 1
    df.iloc[:, 1:] = out
    

    使用 broadcasting 具有 argmax :

    a = df.iloc[:, 1:].values
    df.iloc[:, 1:] = (a.argmax(axis=1)[:,None] == range(a.shape[1])).astype(int)
    

    两者都产生:

       id  level1  level2  level3
    0   1       0       1       0
    1   2       0       0       1
    2   3       0       1       0
    3   4       0       0       1
    4   5       1       0       0
    
        3
  •  2
  •   jpp    6 年前

    int 数据类型。

    idx = df.iloc[:, 1:].eq(1).values.argmax(1)
    df.iloc[:, 1:] = 0
    df.values[np.arange(df.shape[0]), idx+1] = 1
    
    print(df)
    
       id  level1  level2  level3
    0   1       0       1       0
    1   2       0       0       1
    2   3       0       1       0
    3   4       0       0       1
    4   5       1       0       0
    
        4
  •  2
  •   piRSquared    6 年前

    numpy.eye

    v = df.iloc[:, 1:].values
    i = np.eye(3, dtype=np.int64)
    a = v.argmax(1)
    df.iloc[:, 1:] = i[a]
    df
    
       id  level1  level2  level3
    0   1       0       1       0
    1   2       0       0       1
    2   3       0       1       0
    3   4       0       0       1
    4   5       1       0       0
    

    cumsum mask

    df.set_index('id').pipe(
        lambda d: d.mask(d.cumsum(1) > 1, 0)
    ).reset_index()
    
       id  level1  level2  level3
    0   1       0       1       0
    1   2       0       0       1
    2   3       0       1       0
    3   4       0       0       1
    4   5       1       0       0