为了账号安全,请及时绑定邮箱和手机立即绑定

Python:如果有平局,则从 nsmallest 获取第二个 idxmax

Python:如果有平局,则从 nsmallest 获取第二个 idxmax

饮歌长啸 2022-07-19 17:00:43
我有DataFrame如下。我想要得到的是 mininim 1st, 2nd, ... , n Valuefor eachArticle并且知道Name每个的Value来源。df   Article  Name  Value0     A_01  P_01    3601     A_03  P_01    6252     A_01  P_07    3603     A_01  P_09    3704     A_02  P_09    8475     A_03  P_09    6856     A_03  P_18    6507     A_02  P_22    9358     A_03  P_22    6259     A_02  P_25    75010    A_03  P_25    60011    A_01  P_26    50012    A_02  P_26    75013    A_03  P_26    60014    A_01  P_33    48015    A_03  P_33    750我正在使用此代码n minimum value查找n minimum name每个Article. 首先,我转动我df的以获得:list_articles = df['Article'].drop_duplicates()list_names = list(df['Name'].drop_duplicates())pivot_df = df.pivot(index='Article', columns='Name', values='Value').reset_index()pivot_dfName Article   P_01   P_07   P_09   P_18   P_22   P_25   P_26   P_330       A_01  360.0  360.0  370.0    NaN    NaN    NaN  500.0  480.01       A_02    NaN    NaN  847.0    NaN  935.0  750.0  750.0    NaN2       A_03  625.0    NaN  685.0  650.0  625.0  600.0  600.0  750.0然后我运行了 lambda 函数来查找minimum_value和对应minimum_name:for i in range(1, 4):  # minimum 3    pivot_df[f'Min_{i}_Value'] = pivot_df[list_names].T.apply(lambda x: x.nsmallest(i).max())    pivot_df[f'Min_{i}_Name'] = pivot_df[list_names].T.apply(lambda x: x.nsmallest(i).idxmax())这给了我另外 6 列:pivot_dfName Article   P_01   P_07  ...  Min_2_Name  Min_3_Value  Min_3_Name0       A_01  360.0  360.0  ...        P_01        370.0        P_091       A_02    NaN    NaN  ...        P_25        847.0        P_092       A_03  625.0    NaN  ...        P_25        625.0        P_01最后,我的问题是什么?如果你仔细观察,你会发现Min_1_ValueandMin_2_Value是一样的(这是正确的),但是Min_1_Name和Min_2_Name也是一样的,这是不正确的。为什么?因为在原始数据中,同一篇文章有两个具有相同值的名称,所以这是平局。我的代码正在通过 min_n_value 的索引查找 min_n 的名称,因此如果匹配超过 1 个,则不考虑平局的可能性。但是如何Min_2_Name正确分配不是的Min_1_Name呢?可以按字母顺序选择,没关系。你有什么主意吗?
查看完整描述

2 回答

?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

我希望您的解决方案应该简化 - 首先DataFrame.sort_values是 2 列:


df = df.sort_values(['Article','Value'])

print (df)

   Article  Name  Value

0     A_01  P_01    360

2     A_01  P_07    360

3     A_01  P_09    370

14    A_01  P_33    480

11    A_01  P_26    500

9     A_02  P_25    750

12    A_02  P_26    750

4     A_02  P_09    847

7     A_02  P_22    935

10    A_03  P_25    600

13    A_03  P_26    600

1     A_03  P_01    625

8     A_03  P_22    625

6     A_03  P_18    650

5     A_03  P_09    685

15    A_03  P_33    750

然后创建计数器 Series byGroupBy.cumcount并通过 过滤 top3 值boolean indexing,添加MultiIndex并重塑 by Series.unstack,最后MultiIndex按 s 在列中展平f-string:


g = df.groupby('Article').cumcount().add(1)

mask = g < 4

df = df[mask].set_index(['Article',g[mask]]).unstack().sort_index(axis=1, level=1)

df.columns = df.columns.map(lambda x: f'Min_{x[1]}_{x[0]}')

df = df.reset_index()


print (df)

  Article Min_1_Name  Min_1_Value Min_2_Name  Min_2_Value Min_3_Name  \

0    A_01       P_01          360       P_07          360       P_09   

1    A_02       P_25          750       P_26          750       P_09   

2    A_03       P_25          600       P_26          600       P_01   


   Min_3_Value  

0          370  

1          847  

2          625  


查看完整回答
反对 回复 2022-07-19
?
慕莱坞森

TA贡献1810条经验 获得超4个赞

您可以通过用 NaN 替换以前的最小来实现它。


import pandas as pd

import numpy as np

df = pd.DataFrame(

      [['A_01', 'P_01', 360],

       ['A_03', 'P_01', 625],

       ['A_01', 'P_07', 360],

       ['A_01', 'P_09', 370],

       ['A_02', 'P_09', 847],

       ['A_03', 'P_09', 685],

       ['A_03', 'P_18', 650],

       ['A_02', 'P_22', 935],

       ['A_03', 'P_22', 625],

       ['A_02', 'P_25', 750],

       ['A_03', 'P_25', 600],

       ['A_01', 'P_26', 500],

       ['A_02', 'P_26', 750],

       ['A_03', 'P_26', 600],

       ['A_01', 'P_33', 480],

       ['A_03', 'P_33', 750]])


df.columns=['Article','Name','Value']

list_articles = df['Article'].drop_duplicates()

list_names = list(df['Name'].drop_duplicates())

pivot_df = df.pivot(index='Article', columns='Name', values='Value').reset_index()

for i in range(1, 4):

    pivot_df[f'Min_{i}_Value'] = pivot_df[list_names].T.apply(lambda x: x.nsmallest(1).max())

    indices=pivot_df[list_names].T.apply(lambda y: y.nsmallest(1).idxmax())

    pivot_df[f'Min_{i}_Name'] = indices

    for i,x in enumerate(indices):

        pivot_df[x][i]=np.nan


ColsToKeep = [x for x in pivot_df.columns.tolist() if x not in list_names]

ColsToKeep = [x for x in ColsToKeep if x[:3] == 'Min']

ColsToKeep.sort()

ColsToKeep = ['Article'] + ColsToKeep


final_df = pivot_df[ColsToKeep]

final_df


查看完整回答
反对 回复 2022-07-19
  • 2 回答
  • 0 关注
  • 95 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信