【问题标题】:"Bin labels must be one fewer than the number of bin edges" after passing pd.qcut duplicates='drop' kwarg通过 pd.qcut duplicates='drop' kwarg 后,“bin 标签必须比 bin 边缘的数量少一”
【发布时间】:2019-12-25 21:39:08
【问题描述】:

我有一个包含数十万行的df,并且正在创建一个新的数据框,它只包含某些值组的前分位数:

quantiles = (df.groupby(['Person', 'Date'])['Value'].apply(lambda x: pd.qcut(x, 4, labels=[0, 0.25, 0.5, 1], duplicates='drop')))

当我运行它时,我得到:

ValueError: Bin labels must be one fewer than the number of bin edges

尝试将bins 的数量更改为5 后,我仍然收到相同的错误。

我该如何解决这个问题?

【问题讨论】:

  • 不要指定标签。通过删除重复项,您无法保证返回的 bin 数量,因此尝试使用固定长度列表标记它们会导致错误。
  • 啊,我明白了。但是之后我将如何选择最高分位数呢?以前我有:top_quantile_df = df[quantiles.eq(1)],但在我放弃labels 参数后,我得到IndexError: index 0 is out of bounds for axis 0 with size 0
  • 如果您使用labels=False,它将使用从0 开始的整数标记它们。然后,您需要随后屏蔽每组的最大值
  • 抱歉,但我不确定我是否遵循您所说的每组最多掩码的意思。我真的不需要每个组/箱的最大限制 - 真的只想要该特定组的顶部 Value 分位数。

标签: python pandas


【解决方案1】:

我遇到了同样的问题,我这样做是为了克服它。

bins = 数据被切片的次数

labels = 您使用标签进行分类的范围。

labels > bins 时出现此错误

按照以下步骤操作:

步骤。 1:一开始不要传标签

train['MasVnrArea'] = pd.qcut(train['MasVnrArea'],
                          q=5,duplicates='drop')

这将导致:

(-0.001, 16.0]     880
(205.2, 1600.0]    292
(16.0, 205.2]      288
Name: MasVnrArea, dtype: int64

第 2 步:

现在我们可以看到在 binned 上只有三个类别是可能的。 因此,相应地分配标签。就我而言,它是 3。所以我传递了 3 个标签。

bin_labels_MasVnrArea = ['Platinum_MasVnrArea', 
                         'Diamond_MasVnrArea','Supreme_MasVnrArea']
train['MasVnrArea'] = pd.qcut(train['MasVnrArea'],
                              q=5,labels=bin_labels_MasVnrArea,duplicates='drop')

请观看此有关垃圾箱的视频,以便清楚了解。

https://www.youtube.com/watch?v=HofOMf8RgjM

【讨论】:

    【解决方案2】:

    发生这种情况是因为,在从某些组中删除重复项后,传递的标签大小超过了您传递的剪切参数的数量。你必须让它成为动态的东西,就像它在哪里产生的那样只生成标签。

    方法:1

    df.groupby(key)['sales'].transform(lambda x: pd.qcut(x, min(len(x),3), labels=range(1,min(len(x),3)+1), duplicates = 'drop'))
    

    这里我最多切割 3 个,但如果不可能,至少切割 1 或 2 个

    方法:2

    import pandas as pd
    df['rank'] = df.groupby([key])[sales].transform(lambda x: x.rank(method = 'first'))
    
    def q_cut(x, cuts):
        unique_var = len(np.unique([i for i in x]))
        labels1 = range(1, min(unique_var,cuts)+1)
        output = pd.qcut(x, min(unique_var,cuts), labels= labels1, duplicates = 'drop')
        return output
    
    df.groupby([key])['rank'].transform(lambda x: q_cut(x,10))`
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      • 2020-06-05
      • 2015-11-03
      • 2015-04-11
      • 2018-08-05
      相关资源
      最近更新 更多