我是熊猫的新手,所以请原谅我。我想在数据框上应用模式,但需要调整。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 categorical
s,最后在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]
如果你应用到所有列,你应该得到你想要的。