[英]pandas - unstack with most frequent values in MultiIndex DataFrame
[英]pandas dataframe, and using idmax() on the n most frequent values
我有一個pandas數據框,該行的星期幾是行,列的名字是。 數據框內是整數,表示該人在該工作日進入商店的次數。 看起來像這樣:
names 'Martha' 'Johnny' 'Chloe' 'Tim'
'Mon' 3 2 0 7
'Tue' 0 0 3 0
'Wed' 1 12 3 0
'Thu' 5 0 3 0
我想為每個客戶確定他們傾向於購物的一周中的哪幾天,並選擇前兩個。 如果重復(例如Chloe),則順序無關緊要,只要選擇三種可能性中的兩種即可。 萬一某人一天才去商店(例如蒂姆),我希望第二個位置為空。 這是我想要的輸出:
names 'Most frequent' '2nd most freq'
'Martha' 'Thu' 'Mon'
'Johnny' 'Wed' 'Mon'
'Chloe' 'Tue' 'Thu'
'Tim' 'Mon' NaN
我見過類似的問題,詢問是否要擴展argmax(),而不是idmax()。
我當前的計划(用偽代碼):
for customer in dataframe:
for i = 0,1:
if all elements zero:
newdataframe[customer, i] = NaN
else:
newdataframe[customer, i] = dataframe.idxmax()[customer]
dataframe[dataframe.idxmax()[customer], customer] = 0
return newdataframe
我想象一個有更多經驗的人比我可能更有效率地做到這一點。 你怎么看? 有沒有更有效的方法?
由於您還希望第二天成為最頻繁的一天,因此您可以定義一個自定義函數來對每一列進行排序。
# your data
# ===========================
df
Martha Johnny Chloe Tim
Mon 3 2 0 7
Tue 0 0 3 0
Wed 1 12 3 0
Thu 5 0 3 0
# processing
# ======================
def func(col):
# sort index according column values
idx_sorted, _ = zip(*sorted(zip(col.index.values, col.values), key=lambda x: x[1]))
return pd.Series({'most_frequent': idx_sorted[-1], 'second_most_freq': idx_sorted[-2]})
df.apply(func).T
most_frequent second_most_freq
Martha Thu Mon
Johnny Wed Mon
Chloe Thu Wed
Tim Mon Thu
# processing
# ======================
import numpy as np
def func(col):
# sort index according column values
col = col[col > 0]
idx_sorted, _ = zip(*sorted(zip(col.index.values, col.values), key=lambda x: x[1]))
d = dict(zip(np.arange(len(idx_sorted)), idx_sorted[::-1]))
return pd.Series({'most_frequent': d.get(0, np.nan), 'second_most_freq': d.get(1, np.nan)})
df.apply(func).T
most_frequent second_most_freq
Martha Thu Mon
Johnny Wed Mon
Chloe Thu Wed
Tim Mon NaN
df.stack(-1).groupby(level=-1).transform(lambda x: x.argsort(0)).reset_index().pivot('level_1',0).sort_index(axis = 1, ascending = False)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.