python - Python:如果有平局,则从 nsmallest 获取第二个 idxmax
问题描述
我有DataFrame
如下。我想要得到的是 mininim 1st, 2nd, ... , n Value
for eachArticle
并且知道Name
每个的Value
来源。
df
Article Name Value
0 A_01 P_01 360
1 A_03 P_01 625
2 A_01 P_07 360
3 A_01 P_09 370
4 A_02 P_09 847
5 A_03 P_09 685
6 A_03 P_18 650
7 A_02 P_22 935
8 A_03 P_22 625
9 A_02 P_25 750
10 A_03 P_25 600
11 A_01 P_26 500
12 A_02 P_26 750
13 A_03 P_26 600
14 A_01 P_33 480
15 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_df
Name Article P_01 P_07 P_09 P_18 P_22 P_25 P_26 P_33
0 A_01 360.0 360.0 370.0 NaN NaN NaN 500.0 480.0
1 A_02 NaN NaN 847.0 NaN 935.0 750.0 750.0 NaN
2 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_df
Name Article P_01 P_07 ... Min_2_Name Min_3_Value Min_3_Name
0 A_01 360.0 360.0 ... P_01 370.0 P_09
1 A_02 NaN NaN ... P_25 847.0 P_09
2 A_03 625.0 NaN ... P_25 625.0 P_01
并且仅过滤到我感兴趣的那些列之后:
ColsToKeep = [x for x in pivot_df.columns.to_list() 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
:
final_df
Name Article Min_1_Name Min_1_Value Min_2_Name Min_2_Value Min_3_Name Min_3_Value
0 A_01 P_01 360.0 P_01 360.0 P_09 370.0
1 A_02 P_25 750.0 P_25 750.0 P_09 847.0
2 A_03 P_25 600.0 P_25 600.0 P_01 625.0
整个代码:
import pandas as pd
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]],
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(i).max())
pivot_df[f'Min_{i}_Name'] = pivot_df[list_names].T.apply(lambda x: x.nsmallest(i).idxmax())
ColsToKeep = [x for x in pivot_df.columns.to_list() 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]
最后,我的问题是什么?如果你仔细观察,你会发现Min_1_Value
andMin_2_Value
是一样的(这是正确的),但是Min_1_Name
和Min_2_Name
也是一样的,这是不正确的。为什么?因为在原始数据中,同一篇文章有两个具有相同值的名称,所以这是平局。我的代码正在通过 min_n_value 的索引查找 min_n 的名称,因此如果匹配超过 1 个,则不考虑平局的可能性。但是如何Min_2_Name
正确分配不是的Min_1_Name
呢?可以按字母顺序选择,没关系。你有什么主意吗?
解决方案
我希望您的解决方案应该简化 - 首先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
推荐阅读
- python - 如何限制用户看不到 DRF ModelViewSet 中的其他用户数据?
- python - Scrapy 只产生最后一个数据并将scrapy 数据合并为一个
- node.js - 使用 Nodejs 将异步库与 MongoDB 一起使用
- php - 如何在 CakePHP 中包含不相关的实体?
- artifactory - 在 JFrog 的 Artifactory 中的 repo 下,一些工件下载失败
- html - 标题下划线时尚的不同方法是什么?
- openmp - 如何在 OpenMP 并行块中使用 gtest?
- string - Delphi:奇怪的子字符串结果
- spring - spring boot:如何配置自动装配的 WebTestClient
- swift - 在另一个新框架中添加 2 个框架