【问题标题】:Mode of a dataframe with priority具有优先级的数据帧的模式
【发布时间】:2021-05-22 08:05:12
【问题描述】:

我是熊猫新手,请多多包涵。我想在数据帧上应用模式,但需要进行一些调整。列 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中,LowHigh都有相同的频率 strong> 但高优先级更高,因此输出值高。
在 Item_3 中,Low 是最常见的,因此值为 Low。

编辑:
NA 应该被忽略。并且第二个最可用的值应该与日期 2021-01-02 NA 的输出一样,但第二个最频繁的值是 High。

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

【问题讨论】:

  • DataFrame 中是否有不同日期时间的多行?如果是,您可以在有问题的 DataFrame 中添加几行,以便更好地了解需要什么?
  • @jezrael 抱歉给您带来不便,我已按照您的要求更新了数据。
  • 没问题,答案已编辑。

标签: python python-3.x pandas dataframe


【解决方案1】:

我认为有多行具有不同的日期,所以首先通过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

【讨论】:

  • 谢谢它的工作。有什么办法可以保留列的顺序吗?
  • 我只想按日期分组,但仍想保留类型和价格列有什么办法吗?
  • @Rushi - 嗯,什么是逻辑?因为如果聚合 - 每个 dates 使用 sme 公式怎么可能保留其他列?
  • @Rushi 所以你需要lambda x: 'NA' if x[x!= 'NA'].empty else x[x!= 'NA'].mode().iat[0]
  • @Rushi 使用lambda x: x.iat[0] if x[~x.isin('NA', 'other' )].empty else x[~x.isin('NA', 'other' )].mode().iat[0],但如果需要一些 NA 或其他逻辑可能会更复杂。 Tis 解决方案通过 iat[0] 返回第一个值
【解决方案2】:

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

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

当您使用模式时,如果超过 1 个值具有最高频率,它会返回多个值。但它也会对结果进行排序。默认情况下按字母顺序排列,但由于您将列转换为分类,它将使用排名。

df["Item_2"].mode()

会回来

0    High
1     Low
Name: Item_2, dtype: category

使用[0] 索引,您始终可以提取最高值。

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

如果你将它应用到所有列,你应该得到你正在寻找的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2011-01-18
    • 2012-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多