具有优先级的数据帧模式

时间:2021-02-19 10:22:44

标签: python python-3.x pandas dataframe

我是熊猫的新手,所以请耐心等待。我想在数据帧上应用模式,但要进行调整。列 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 的频率如何,只要日期有单个高/低/中,我都想选择出现次数/频率第二高的分类值

2 个答案:

答案 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
相关问题