具有优先级的数据帧的模式



我是熊猫的新手,所以请原谅我。我想在数据框上应用模式,但需要调整。Item_1、Item_2、Item_3列可以有[High、Medium、Low、NA]四个值。高优先级最高,低优先级最低。NA应该被忽略。
数据如下:

date       Type  Item_1   Item_2  Item_3 Price
0   2021-01-01  A    High     Low     Low     20   
1   2021-01-01  A    High     Low     Low     20    
2   2021-01-01  A    Low      High    Low     20   
3   2021-01-01  A    Medium   High    High    20    
4   2021-01-01  B    Low      High    Low     15   
5   2021-01-01  B    Medium   High    High    15
6   2021-01-01  B    Low      Low     Medium  15
6   2021-01-02  A    NA       High    NA      30    
7   2021-01-02  A    NA       High    NA      30    
8   2021-01-02  A    NA       NA      NA      30
9   2021-01-02  A    NA       NA      Low     30
10  2021-01-02  A    NA       NA      Low     30
11  2021-01-02  A    NA       Low     High    30

预期输出:

date       Type  Item_1   Item_2  Item_3  Price
0   2021-01-01  A    High     High    Low     20  
1   2021-01-01  B    Low      High    High    15
2   2021-01-02  A    NA       High    Low     30   
如您所见,Item_1的第一行现在有值因为它最常见。
但在Item_2低两个具有相同频率但高有更多的优先级,因此价值是高的输出。

Item_3中Low是最常见的,因此值为Low。 编辑:
NA应忽略。第二个可用值应该与日期2021-01-02的输出相同,NA的频率最高,但第二个最常见的值是High。

值NA不对应NaN,而是一个字符串对象。类似于其他分类值。只是,无论NA的频率如何,只要一个日期有一个High/Low/Medium,我就想选择出现/频率第二高的分类值

我认为有不同日期的多行,因此首先由DataFrame.melt重塑,然后将值转换为ordered categoricals,最后在lambda函数中获得GroupBy.agg中每组的第一模式,最后由Series.unstack重塑:

cols = df.columns
df = df.melt(['date','Type','Price'])
df["value"] = pd.Categorical(df["value"], 
categories=["High", "Medium", "Low"], 
ordered=True)
df = (df.groupby(['date','Type','Price','variable'])['value']
.agg(lambda x: x.mode().iat[0])
.unstack()
.rename_axis(None, axis=1)
.reset_index()
.reindex(cols, axis=1))
print (df)
date Type  Item_1 Item_2 Item_3  Price
0  2021-01-01    A    High   High    Low     20
1  2021-01-01    B     Low   High   High     15
2  2021-01-02    A  Medium    Low   High     30

您可以将Item列转换为分类列并提供排名(您的优先级)。例如Item_2:

df["Item_2"] = pd.Categorical(df["Item_2"], ["High", "Medium", "Low"])

当你使用mode时,如果超过一个值具有最高频率,它将返回多个值。但它也会命令结果。默认情况下按字母顺序排列,但由于您将列转换为分类列,因此它将使用排名。

df["Item_2"].mode()

将返回

0    High
1     Low
Name: Item_2, dtype: category

使用[0]索引,您总是可以提取顶部值。

df["Item_2"].mode()[0]

如果你应用到所有列,你应该得到你想要的。

最新更新