13

我的数据框的最小值为零。我正在尝试使用 的precisioninclude_lowest参数pandas.cut(),但我无法让间隔由整数组成,而不是由一位小数组成的浮点数。我也不能让最左边的间隔停在零。

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

sns.set(style='white', font_scale=1.3)

df = pd.DataFrame(range(0,389,8)[:-1], columns=['value'])
df['binned_df_pd'] = pd.cut(df.value, bins=7, precision=0, include_lowest=True)
sns.pointplot(x='binned_df_pd', y='value', data=df)
plt.xticks(rotation=30, ha='right')

在此处输入图像描述

我尝试设置precision为 -1、0 和 1,但它们都输出一位小数浮点数。pandas.cut()帮助确实提到 x-min 和 x-max 值扩展了 x 范围的 0.1 %,但我认为也许可以include_lowest以某种方式抑制这种行为。我目前的解决方法涉及导入 numpy:

import numpy as np

bin_counts, edges = np.histogram(df.value, bins=7)
edges = [int(x) for x in edges]
df['binned_df_np'] = pd.cut(df.value, bins=edges, include_lowest=True)

sns.pointplot(x='binned_df_np', y='value', data=df)
plt.xticks(rotation=30, ha='right')

在此处输入图像描述

pandas.cut()有没有办法在不使用 numpy的情况下直接获得非负整数作为区间边界?

编辑:我刚刚注意到指定right=False使最低间隔变为0而不是-0.4。它似乎优先include_lowest,因为更改后者并没有任何可见的效果right=False。以下间隔仍指定小数点后一位。

在此处输入图像描述

4

3 回答 3

5

你应该专门设置labels参数

准备工作:

lower, higher = df['value'].min(), df['value'].max()
n_bins = 7

建立标签:

edges = range(lower, higher, (higher - lower)/n_bins) # the number of edges is 8
lbs = ['(%d, %d]'%(edges[i], edges[i+1]) for i in range(len(edges)-1)]

设置标签:

df['binned_df_pd'] = pd.cut(df.value, bins=n_bins, labels=lbs, include_lowest=True)
于 2018-03-07T10:43:22.487 回答
3

其他答案(包括 OP 的np.histogram解决方法)似乎都不起作用了。他们有赞成票,所以我不确定这些年来是否发生了变化。

IntervalIndex要求所有区间都以相同方式闭合,因此[0, 53]不能与 共存(322, 376]


以下是基于重新标记方法的两种工作解决方案:

  1. 没有 numpy,重用pd.cut边缘作为pd.cut标签

    bins = 7
    
    _, edges = pd.cut(df.value, bins=bins, retbins=True)
    labels = [f'({abs(edges[i]):.0f}, {edges[i+1]:.0f}]' for i in range(bins)]
    
    df['bin'] = pd.cut(df.value, bins=bins, labels=labels)
    
    #     value         bin
    # 1       8     (0, 53]
    # 2      16     (0, 53]
    # ..    ...         ...
    # 45    360  (322, 376]
    # 46    368  (322, 376]
    
  2. 使用 numpy,np.linspace边缘转换为pd.cut标签

    bins = 7
    
    edges = np.linspace(df.value.min(), df.value.max(), bins+1).astype(int)
    labels = [f'({edges[i]}, {edges[i+1]}]' for i in range(bins)]
    
    df['bin'] = pd.cut(df.value, bins=bins, labels=labels)
    
    #     value         bin
    # 1       8     (0, 53]
    # 2      16     (0, 53]
    # ..    ...         ...
    # 45    360  (322, 376]
    # 46    368  (322, 376]
    

注意:仅更改了标签,因此基础分箱仍会发生 0.1% 的边距。


pointplot()输出(从熊猫 1.2.4 开始):

sns.pointplot(x='bin', y='value', data=df)
plt.xticks(rotation=30, ha='right')

于 2021-06-06T15:26:59.933 回答
0

@joelostblom,您已经完成了大部分工作,而不是使用 numpy,只需使用 pandas 已经提供的内容,即返回垃圾箱。

_, edges = pd.cut(df.value, bins=7, retbins=True)
edges = [int(x) for x in edges]
df['binned_df_np'] = pd.cut(df.value, bins=edges, include_lowest=True)
于 2021-03-07T02:51:28.260 回答