joe*_*lom 10 python intervals bins pandas
我的数据帧为零,为最低值.我试图使用precision和include_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')
Run Code Online (Sandbox Code Playgroud)
我已经尝试设置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')
Run Code Online (Sandbox Code Playgroud)
有没有办法在pandas.cut()不使用numpy的情况下直接获得非负整数作为区间边界?
编辑:我刚注意到指定right=False使最低间隔移到0而不是-0.4.它似乎优先于include_lowest,因为改变后者并没有任何明显的效果right=False.仍然使用一个小数点指定以下间隔.
小智 6
你应该专门设置labels参数
lower, higher = df['value'].min(), df['value'].max()
n_bins = 7
Run Code Online (Sandbox Code Playgroud)
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)]
Run Code Online (Sandbox Code Playgroud)
df['binned_df_pd'] = pd.cut(df.value, bins=n_bins, labels=lbs, include_lowest=True)
Run Code Online (Sandbox Code Playgroud)
其他答案(包括OP的np.histogram解决方法)似乎都不再有效。他们有投票,所以我不确定这些年来是否发生了变化。
IntervalIndex要求所有区间都以相同的方式闭合,因此[0, 53]不能与 共存(322, 376]。
以下是基于重新标记方法的两个可行解决方案:
没有 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]
Run Code Online (Sandbox Code Playgroud)
使用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]
Run Code Online (Sandbox Code Playgroud)
注意:仅更改标签,因此基础分箱仍将以 0.1% 的边距进行。
pointplot()输出(从 pandas 1.2.4 开始):
sns.pointplot(x='bin', y='value', data=df)
plt.xticks(rotation=30, ha='right')
Run Code Online (Sandbox Code Playgroud)