我是熊猫的新手,所以请耐心等待。我想在数据帧上应用模式,但要进行调整。列 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 中的第一行现在将 High 作为其最常用的值。
但是在Item_2中低和高具有相同的频率 但 High 有更高的优先级,因此输出的值是 High。
在 Item_3 中,低是最常见的,因此值低。
编辑:
NA 应该被忽略。和第二个最有用的值应该作为输出,如日期 2021-01-02 NA 的频率最高,但第二个最频繁的值是高。
值 NA 不对应于 NaN 而是一个字符串对象。类似于其他分类值。只是,无论 NA 的频率如何,只要日期有单个高/低/中,我都想选择出现次数/频率第二高的分类值
答案 0 :(得分:1)
您可以将您的项目列转换为分类并提供排名(您的优先级)。例如Item_2
:
df["Item_2"] = pd.Categorical(df["Item_2"], ["High", "Medium", "Low"])
当您使用 mode 时,如果超过 1 个值的频率最高,它会返回多个值。但它也会对结果进行排序。默认情况下按字母顺序排列,但由于您将列转换为分类列,它将改为使用排名。
df["Item_2"].mode()
会回来
0 High
1 Low
Name: Item_2, dtype: category
使用 [0]
索引,您始终可以提取最高值。
df["Item_2"].mode()[0]
如果您将其应用于所有列,您应该会得到您想要的。
答案 1 :(得分:1)
我认为有多个具有不同日期的行,因此首先通过 DataFrame.melt
进行整形,然后将值转换为 ordered categorical
并最后在 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