首页 文章

获取Dataframe Pandas中最高 Value 的列和行索引

提问于
浏览
5

我想知道是否有办法找到数据框中最高值的位置(列和行索引) . 所以,例如,如果我的数据框看起来像这样:

A         B         C         D         E
0  100       9         1         12        6
1  80        10        67        15        91
2  20        67        1         56        23
3  12        51        5         10        58
4  73        28        72        25        1

如何获得如下所示的结果: [0, 'A'] 使用Pandas?

6 回答

  • 0

    使用np.argmax

    NumPy的 argmax 可以提供帮助:

    >>> df.stack().index[np.argmax(df.values)]
    (0, 'A')
    

    步骤

    df.values 是一个二维NumPy数组:

    >>> df.values
    array([[100,   9,   1,  12,   6],
           [ 80,  10,  67,  15,  91],
           [ 20,  67,   1,  56,  23],
           [ 12,  51,   5,  10,  58],
           [ 73,  28,  72,  25,   1]])
    

    argmax 为您提供"flattened"数组最大值的索引:

    >>> np.argmax(df.values)
    0
    

    现在,您可以使用此索引查找堆叠数据帧上的行列位置:

    >>> df.stack().index[0]
    (0, 'A')
    

    快速替代方案

    如果您需要快速,请尽可能少地执行 . 仅在NumPy数组上工作以查找索引 np.argmax 似乎是最好的:

    v = df.values
    i, j = [x[0] for x in np.unravel_index([np.argmax(v)], v.shape)]
    [df.index[i], df.columns[j]]
    

    结果:

    [0, 'A']
    

    时间

    时序最适合lareg数据帧:

    df = pd.DataFrame(data=np.arange(int(1e6)).reshape(-1,5), columns=list('ABCDE'))
    

    排序最慢到最快:

    面具:

    %timeit df.mask(~(df==df.max().max())).stack().index.tolist()
    33.4 ms ± 982 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

    Stack-idmax

    %timeit list(df.stack().idxmax())
    17.1 ms ± 139 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    Stack-argmax

    %timeit df.stack().index[np.argmax(df.values)]
    14.8 ms ± 392 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    哪里

    %%timeit
    i,j = np.where(df.values == df.values.max())
    list((df.index[i].values.tolist()[0],df.columns[j].values.tolist()[0]))
    
    4.45 ms ± 84.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    Argmax-unravel_index

    %%timeit
    
    v = df.values
    i, j = [x[0] for x in np.unravel_index([np.argmax(v)], v.shape)]
    [df.index[i], df.columns[j]]
    
    499 µs ± 12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    比较

    d = {'name': ['Mask', 'Stack-idmax', 'Stack-argmax', 'Where', 'Argmax-unravel_index'],
         'time': [33.4, 17.1, 14.8, 4.45, 499],
         'unit': ['ms', 'ms', 'ms', 'ms', 'µs']}
    
    
    timings = pd.DataFrame(d)
    timings['seconds'] = timings.time * timings.unit.map({'ms': 1e-3, 'µs': 1e-6})
    timings['factor slower'] = timings.seconds / timings.seconds.min()
    timings.sort_values('factor slower')
    

    输出:

    name    time unit   seconds  factor slower
    4  Argmax-unravel_index  499.00   µs  0.000499       1.000000
    3                 Where    4.45   ms  0.004450       8.917836
    2          Stack-argmax   14.80   ms  0.014800      29.659319
    1           Stack-idmax   17.10   ms  0.017100      34.268537
    0                  Mask   33.40   ms  0.033400      66.933868
    

    因此,对于大数据帧,“Argmax-unravel_index”版本似乎要快一到两个数量级,即通常速度最重要的地方 .

  • 6

    使用stackSeriesMultiIndexidxmax作为最大值的索引:

    print (df.stack().idxmax())
    (0, 'A')
    
    print (list(df.stack().idxmax()))
    [0, 'A']
    

    详情:

    print (df.stack())
    0  A    100
       B      9
       C      1
       D     12
       E      6
    1  A     80
       B     10
       C     67
       D     15
       E     91
    2  A     20
       B     67
       C      1
       D     56
       E     23
    3  A     12
       B     51
       C      5
       D     10
       E     58
    4  A     73
       B     28
       C     72
       D     25
       E      1
    dtype: int64
    
  • 0

    mask max

    df.mask(~(df==df.max().max())).stack().index.tolist()
    Out[17]: [(0, 'A')]
    
  • 1

    在我看来,对于更大的数据集,stack()变得效率低下,让我们使用 np.where 来返回索引位置:

    i,j = np.where(df.values == df.values.max())
    list((df.index[i].values.tolist()[0],df.columns[j].values.tolist()[0]))
    

    输出:

    [0, 'A']
    

    更大的数据名称的时间:

    df = pd.DataFrame(data=np.arange(10000).reshape(-1,5), columns=list('ABCDE'))
    

    np.where方法

    > %%timeit i,j = np.where(df.values == df.values.max())
    > list((df.index[i].values.tolist()[0],df.columns[j].values.tolist()[0]))
    

    1000次循环,最佳为3:每循环364μs

    其他堆栈方法

    > %timeit df.mask(~(df==df.max().max())).stack().index.tolist()
    

    100循环,最佳3:每循环7.68 ms

    > %timeit df.stack().index[np.argmax(df.values)`]
    

    10个循环,最佳3:50.5 ms每个循环

    > %timeit list(df.stack().idxmax())
    

    1000次循环,最佳3:每循环1.58 ms

    更大的数据帧:

    df = pd.DataFrame(data=np.arange(100000).reshape(-1,5), columns=list('ABCDE'))
    

    分别:

    1000 loops, best of 3: 1.62 ms per loop
    10 loops, best of 3: 18.2 ms per loop
    100 loops, best of 3: 5.69 ms per loop
    100 loops, best of 3: 6.64 ms per loop
    
  • 2

    这应该工作:

    def max_df(df):
        m = None
        p = None
        for idx, item in enumerate(df.idxmax()):
            c = df.columns[item]
            val = df[c][idx]
            if m is None or val > m:
                m = val
                p = idx, c
        return p
    

    这使用idxmax函数,然后比较它返回的所有值 .

    用法示例:

    >>> df
    
         A  B
    0  100  9
    1   90  8
    >>> max_df(df)
    
    (0, 'A')
    

    这是一个单行(为了好玩):

    def max_df2(df):
        return max((df[df.columns[item]][idx], idx, df.columns[item]) for idx, item in enumerate(df.idxmax()))[1:]
    
  • 8
    print('Max value:', df.stack().max())
    print('Parameters :', df.stack().idxmax())
    

    这是imho的最佳方式 .

相关问题