假設有兩個 pandas DataFrame:df1 & df2。df1 是一個方形資料框,如下所示
import numpy as np
import pandas as pd
item_names = [2,7,9,10,11,13,14,21,24]
np.random.seed(123)
nums = np.round(np.random.random(size=(9,9)),2)
df1 = pd.DataFrame(nums, index=item_names, columns=item_names)
df1 輸出:
2 7 9 10 11 13 14 21 24
2 0.70 0.29 0.23 0.55 0.72 0.42 0.98 0.68 0.48
7 0.39 0.34 0.73 0.44 0.06 0.40 0.74 0.18 0.18
9 0.53 0.53 0.63 0.85 0.72 0.61 0.72 0.32 0.36
10 0.23 0.29 0.63 0.09 0.43 0.43 0.49 0.43 0.31
11 0.43 0.89 0.94 0.50 0.62 0.12 0.32 0.41 0.87
13 0.25 0.48 0.99 0.52 0.61 0.12 0.83 0.60 0.55
14 0.34 0.30 0.42 0.68 0.88 0.51 0.67 0.59 0.62
21 0.67 0.84 0.08 0.76 0.24 0.19 0.57 0.10 0.89
24 0.63 0.72 0.02 0.59 0.56 0.16 0.15 0.70 0.32
df2 存盤專案及其對應的組資訊,例如
df2 = pd.DataFrame({'item': item_names,
'group':['a1','a1','a1','a2',
'a2','a2','a2','a3','a3']})
df2 輸出:
item group
0 2 a1
1 7 a1
2 9 a1
3 10 a2
4 11 a2
5 13 a2
6 14 a2
7 21 a3
8 24 a3
目標是撰寫一個函式,該函式可以使用這兩個 DataFrame 的資訊根據相應的值(最大)選擇特定行中的前 N ??個專案(專案名稱)。但是,回傳的前 N ??個專案和查詢專案ALL MUST來自“不同的組”。如
查詢項 (item = 10) 在 df1 (item = 10) 的第 4 行。前 2 個退回的專案將[9, 21]不是[9, 14]。因為,專案 10 來自 group = a2 并且任何回傳的專案(前 N 個)都不應該來自 a2 組。我已經檢查了Scott Boston 解決方案是否存在類似問題,但它無法避免前 N 個專案和查詢專案來自同一組。有什么建議?非常感謝
uj5u.com熱心網友回復:
不確定您到底想要什么……但這可能會為您指明一個方向:
import pandas as pd
import numpy as np
s2 = df2.set_index('item').group
mask = np.equal.outer(df1.index.map(s2.get), df1.columns.map(s2.get))
stacked = df1.mask(mask).stack().rename_axis(['x', 'y']).to_frame(name='v')
stacked.sort_values(['x', 'v'], ascending=[True, False]).groupby('x').head(2)
v
x y
2 14 0.98
11 0.72
7 14 0.74
10 0.44
9 10 0.85
11 0.72
10 9 0.63
21 0.43
11 9 0.94
7 0.89
13 9 0.99
21 0.60
14 24 0.62
21 0.59
21 7 0.84
10 0.76
24 7 0.72
2 0.63
uj5u.com熱心網友回復:
IIUC,您要選擇 N 個最大值,不包括同一組中的值。
這是一個執行此操作的函式:
def get_top_N(idx, N=2):
group = df2.set_index('item')['group']
incl = group[group.ne(group[idx])].index
return df1.loc[idx, incl].nlargest(2).index.to_list()
get_top_N(10)
# [9, 21]
如果您還想確保所有值都來自不同的組(這不清楚是否需要,因為您的示例就是這種情況)。您還可以執行以下操作:
def get_top_N_diff(idx, N=2):
group = df2.set_index('item')['group']
incl = group[group.ne(group[idx])].index
s = df1.loc[idx, incl]
return s.sort_values(ascending=False).groupby(group).idxmax().to_list()[:N]
get_top_N(11) # same group
# [9, 7]
get_top_N_diff(11) # different groups
# [9, 24]
uj5u.com熱心網友回復:
對您提到的答案的修改:
def get_top(df1, df2, item_name, number_items):
val = df1.loc[[item_name]].T.merge(df2, left_index=True, right_on = 'item')
val = val[val['group']!=val.loc[val['item']==item_name, 'group'].values[0]]
return (val.sort_values(item_name, ascending=False)
.groupby('group')
.head(1)
.head(number_items)['item']
.to_numpy())
>>> get_top(df1, df2, 10, 2)
array([ 9, 21])
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/448653.html
上一篇:ValueError:嘗試從字典創建pandasDataFrame時,每列陣列都必須是一維的。為什么?
下一篇:ValueError:時間資料“14.03.202200:00:00.000GMT-0400”與格式“%d.%m.%Y%H:%M:%S.%f%z”不匹配(匹配)
