【问题标题】:Python/Pandas: Finding index for the nlargest and keeping only those above a valuePython/Pandas:查找 nlargest 的索引并仅保留高于某个值的索引
【发布时间】:2020-05-22 19:59:52
【问题描述】:

我想检索与 n 个最大值对应的列集的 n 个列名。 然后,仅当值高于给定阈值时,这些名称才会保存在列表中。

例如,给定三个列“Paul”、“Eric”、“Marc”,假设我最多需要 2 个列名,阈值为 0.5。然后,我将按如下方式获得“最佳”列:

import pandas as pd
import numpy as np

start = '2020-01-01 00:00+00:00'
end = '2020-01-01 05:00+00:00'

pr1h = pd.period_range(start=start, end=end, freq='1h')
r = len(pr1h)

df = pd.DataFrame(np.random.rand(r,3), index=pr1h, columns=['Paul', 'Marc', 'Eric'])

处理后:

df
                      Paul      Marc      Eric            Bests
2020-01-01 00:00  0.124974  0.525182  0.415339         ['Marc']
2020-01-01 01:00  0.991917  0.489479  0.668359 ['Paul', 'Eric']
2020-01-01 02:00  0.204156  0.610034  0.644715 ['Eric', 'Marc']
2020-01-01 03:00  0.385546  0.981641  0.089667         ['Marc']
2020-01-01 04:00  0.912330  0.711822  0.148064 ['Paul', 'Marc']
2020-01-01 05:00  0.301186  0.313572  0.323487               []

我可以在 SOthis question/answer 上找到,它显示了一种根据给定行中值的排名获取索引的方法。 我想这可能是一个起点(可能在速度方面没有优化,因为运行了几次,但它似乎是一个好的开始。

然后我可以:

df1['1st_largest'] = df.columns[df.values.argsort(1)[:,-1]]
df2['2nd_largest'] = df.columns[df.values.argsort(1)[:,-2]]

我的数组不应该超过 20 到 50 列,所以我保留了 argsort 而不是 argpartition

但现在,我被困住了。我不知道如何检查与这些列之一相关的值是否高于 0.5,以便我可以将其放入列表中。

欢迎任何帮助,谢谢!

【问题讨论】:

  • 您好@r.ook,预期输出是“最佳”列。如果您运行代码,您会看到它只为您提供了 3 列“Paul”、“Marc”、“Eric”。最佳
  • 啊,好吧,我误解了这个问题。我想@QuangHoang 让你得到了保障。

标签: python pandas


【解决方案1】:

一种方法是使用wherestack 屏蔽数据框:

df['Bests'] = (df.where(df.gt(0.5))         # change 0.5 to your threshold
                 .stack().groupby(level=0)
                 .apply(lambda x: x.nlargest(2).index
                                   .get_level_values(1).to_list()
                       )
              )

输出:

                      Paul      Marc      Eric         Bests
2020-01-01 00:00  0.124974  0.525182  0.415339        [Marc]
2020-01-01 01:00  0.991917  0.489479  0.668359  [Paul, Eric]
2020-01-01 02:00  0.204156  0.610034  0.644715  [Eric, Marc]
2020-01-01 03:00  0.385546  0.981641  0.089667        [Marc]
2020-01-01 04:00  0.912330  0.711822  0.148064  [Paul, Marc]
2020-01-01 05:00  0.301186  0.313572  0.323487           NaN

【讨论】:

  • 谢谢,我保留了您的解决方案。非常感谢!
【解决方案2】:

与 Quang 的想法相同,但使用 GroupBy.agg(list):

dfg = df.where(df>0.5).stack().groupby(level=0).nlargest(2)
df['Bests'] = dfg.reset_index(level=2).groupby(level=0)['level_2'].agg(list)

                      Paul      Marc      Eric         Bests
2020-01-01 00:00  0.494089  0.500048  0.398106        [Marc]
2020-01-01 01:00  0.571067  0.896135  0.445951  [Marc, Paul]
2020-01-01 02:00  0.769473  0.830661  0.909551  [Eric, Marc]
2020-01-01 03:00  0.828074  0.025853  0.670196  [Paul, Eric]
2020-01-01 04:00  0.651157  0.641126  0.346411  [Paul, Marc]
2020-01-01 05:00  0.752359  0.970789  0.231323  [Marc, Paul]

【讨论】:

  • 斋月穆巴拉克 :)
  • @Erfan,非常感谢您的帮助。我比较了两种解决方案的执行时间,不幸的是,这个解决方案的执行时间确实比 Quang 多两倍。不过还是谢谢!
猜你喜欢
  • 2013-09-08
  • 2012-11-14
  • 2014-11-26
  • 2018-03-14
  • 2018-09-18
  • 2018-11-06
  • 1970-01-01
  • 2018-01-15
相关资源
最近更新 更多