【问题标题】:Sorting each row and select the top three values from a dataframe对每一行进行排序并从数据框中选择前三个值
【发布时间】:2018-04-27 02:32:20
【问题描述】:

我有一个看起来像这样的数据框:

device_id   s2  s41 s47 s14
30          0   0   0   0.003
125         0   0   0   0
32          0   0   0   0
45          0   0   0   0

目标是从每行中获取 3 个最高的 s,如果有匹配项,则选择最大索引。例如,对于第一行,s2、s41 和 s47 之间存在匹配,因此将选择 s47 和 s41。因此,第 1 行的选择将是 s14、s47 和 s41。有超过 200 万条记录和超过 250 条记录,因此我需要一种有效的方法来做到这一点。我尝试过使用 iterrows,然后对每一行进行排序,但速度很慢,所有数据都需要一个多小时。

最终目标是在字典中搜索 s (s14, s47, s41),其中这些值是键,并从那里获取适当的值。

有人可以帮助我有效地做到这一点。 谢谢

【问题讨论】:

    标签: python pandas sorting dictionary


    【解决方案1】:

    我会使用heapq's nlargest:

    In [11]: df
    Out[11]:
       device_id  s2  s41  s47    s14
    0         30   0    0    0  0.003
    1        125   0    0    0  0.000
    2         32   0    0    0  0.000
    3         45   0    0    0  0.000
    
    In [12]: nlargest(3, df.columns[1:], key=lambda x: int(x[1:]))
    Out[12]: ['s47', 's41', 's14']
    
    In [13]: df[["device_id"] + nlargest(3, df.columns[1:], key=lambda x: int(x[1:]))]
    Out[13]:
       device_id  s47  s41    s14
    0         30    0    0  0.003
    1        125    0    0  0.000
    2         32    0    0  0.000
    3         45    0    0  0.000
    

    注意:如果 device_id 是索引,它会更容易一些:

    In [21]: df1
    Out[21]:
               s2  s41  s47    s14
    device_id
    30          0    0    0  0.003
    125         0    0    0  0.000
    32          0    0    0  0.000
    45          0    0    0  0.000
    
    In [22]: df1[nlargest(3, df1.columns, key=lambda x: int(x[1:]))]
    Out[22]:
               s47  s41    s14
    device_id
    30           0    0  0.003
    125          0    0  0.000
    32           0    0  0.000
    45           0    0  0.000
    

    【讨论】:

      【解决方案2】:

      我不知道 pandas,但我知道它是基于 numpy 的,所以这里有一个 numpy 解决方案。它使用 argpartition 有效地获取每行中最大 4 个的索引。不幸的是,numpy 使用的算法不稳定,所以如果这四个中最小的两个相等,我们必须进行完全排序,排序让我们可以选择稳定的算法。

      代码(无法检查我的装备上的 2m 行 b/c 内存,但 0.5m 需要 2 秒左右):

      import numpy as np
      
      def stable_high_3(data):
          n, m = data.shape
          high_4 = np.argpartition(data, np.arange(m-4, m), axis=-1)[:, -4:]
          must_check = np.where(data[np.arange(n), high_4[:, 0]]
                                == data[np.arange(n), high_4[:, 1]])[0]
          high_4[must_check, -3:] = np.argsort(data[must_check], axis=-1,
                                               kind='mergesort')[:, -3:]
          return high_4[:, -3:]
      
      data = np.reshape(np.arange(30)%5, (-1, 6))
      print(data)
      print(stable_high_3(data))
      
      data = np.reshape(np.arange(256*2**18)%50, (-1, 256))
      stable_high_3(data)
      

      打印

      [[0 1 2 3 4 0]
       [1 2 3 4 0 1]
       [2 3 4 0 1 2]
       [3 4 0 1 2 3]
       [4 0 1 2 3 4]]
      [[2 3 4]
       [1 2 3]
       [5 1 2]
       [0 5 1]
       [4 0 5]]
      

      【讨论】:

        猜你喜欢
        • 2022-11-27
        • 2020-04-20
        • 1970-01-01
        • 2017-10-17
        • 1970-01-01
        • 2014-03-24
        • 2018-09-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多