首页 文章

Pandas:每行最大值的矢量化操作

提问于
浏览
5

我有以下pandas dataframe df

index        A    B    C
    1        1    2    3
    2        9    5    4
    3        7    12   8
    ...      ...  ...  ...

我希望每行的最大值保持不变,所有其他值变为 -1 . 因此输出看起来像这样:

index        A    B    C
    1       -1   -1    3
    2        9   -1   -1
    3       -1    12  -1
    ...      ...  ...  ...

通过使用 df.max(axis = 1) ,我得到一个pandas Series ,其中每行的最大值 . 但是,我正在寻找一个矢量化,快速实现 .

3 回答

  • 1

    考虑使用where

    >>> df.where(df.eq(df.max(1), 0), -1)
           A   B  C
    index          
    1     -1  -1  3
    2      9  -1 -1
    3     -1  12 -1
    

    这里 df.eq(df.max(1), 0) 是一个标记行最大值的布尔DataFrame;真值(最大值)保持不变,而假值变为-1 . 如果您愿意,也可以使用Series或其他DataFrame而不是标量 .

    该操作也可以在现场完成(通过 inplace=True ) .

  • 2

    您可以通过eqmax按行比较来创建布尔 mask ,然后应用反向 mask

    print df
           A   B  C
    index          
    1      1   2  3
    2      9   5  4
    3      7  12  8
    
    print df.max(axis=1)
    index
    1     3
    2     9
    3    12
    dtype: int64
    
    mask = df.eq(df.max(axis=1), axis=0)
    print mask
               A      B      C
    index                     
    1      False  False   True
    2       True  False  False
    3      False   True  False
    
    df[~mask] = -1
    print df
           A   B  C
    index          
    1     -1  -1  3
    2      9  -1 -1
    3     -1  12 -1
    

    全部一起:

    df[~df.eq(df.max(axis=1), axis=0)] = -1
    print df
           A   B  C
    index          
    1     -1  -1  3
    2      9  -1 -1
    3     -1  12 -1
    
  • 4

    为每个值创建一个大小相同的 df 的新数据框 . 然后使用 enumerate 获取给定行中的第一个最大值,使用标量的整数获取/设置( iat ) .

    df2 = pd.DataFrame(-np.ones(df.shape), columns=df.columns, index=df.index)
    
    for row, col in enumerate(np.argmax(df.values, axis=1)):
        df2.iat[row, col] = df.iat[row, col]
    
    >>> df2
       0   1  2
    0 -1  -1  3
    1  9  -1 -1
    2 -1  12 -1
    

    Timings

    df = pd.DataFrame(np.random.randn(10000, 10000))
    
    %%timeit
    df2 = pd.DataFrame(-np.ones(df.shape))
    for row, col in enumerate(np.argmax(df.values, axis=1)):
        df2.iat[row, col] = df.iat[row, col]
    1 loops, best of 3: 1.19 s per loop
    
    %timeit df.where(df.eq(df.max(1), 0), -1)
    1 loops, best of 3: 6.27 s per loop
    
    # Using inplace=True
    %timeit df.where(df.eq(df.max(1), 0), -1, inplace=True)
    1 loops, best of 3: 5.58 s per loop
    
    %timeit df[~df.eq(df.max(axis=1), axis=0)] = -1
    1 loops, best of 3: 5.65 s per loop
    

相关问题