盘一盘 Python 特别篇 22 - 分箱之 cut

2020-09-08 15:07:50 浏览数 (2)

当要
  • qcut 分组后保证每组含有的数据几乎一样多,每组的边界会被反算出来
  • cut 自定义每组的边界,每组组含有的数据个数不同

首先引入要用到的工具包:

代码语言:javascript复制
import pandas as pd
import numpy as np
import seaborn as sns
sns.set_style('whitegrid')

数据

本贴继续使用上贴的数据,回顾一下是 2018 年的销售数据。接下来用 info(), head(), tail() 几个函数来看看数据集的大小、行标签和列标签。

代码语言:javascript复制
raw_df = pd.read_excel('sales.xlsx')
raw_df.info()
代码语言:javascript复制
raw_df.head(3).append(raw_df.tail(3))

将其按 account number 和 name 分组,并对 ext price 加总得到:

代码语言:javascript复制
df = raw_df.groupby(['account number', 'name'])['ext price'].sum().reset_index()
df.inf()
代码语言:javascript复制
df

cut

在实际案例中,可通过业务规则定义箱。就拿新加坡航空公司飞行会员计划,25,000 英里是银卡 (silver) 而 50,000 英里是金卡 (gold),并且它不会根据数据的年度变化而变化。如果我们要定义箱边界 (25,000, 50,000),我们就不能使用 qcut 而是 cut 了,因为后者可以自定义箱边界。

首先将数据分成四个箱,注意每个箱的上界和下界之差为 32,265。

代码语言:javascript复制
pd.cut(df['ext price'], bins=4)

我们来看看每组的分布,很显然每组含的数据个数分别是 12,5,2,1,都不一样。这就是 cut 和 qcut 最重要的差别。

代码语言:javascript复制
pd.cut(df['ext price'], bins=4).value_counts()

接下来定义箱的确切边界,通过设置参数 bins 即可。

代码语言:javascript复制
cut_labels_4 = ['silver', 'gold', 'platinum', 'diamond']
cut_bins = [0, 70000, 100000, 130000, 200000]
df['cut_ex1'] = pd.cut(df['ext price'], bins=cut_bins, labels=cut_labels_4)
df.head()

此外我们还可以用 np.linspace() 函数来创建等距的箱,用 8 个箱来举例,那么 linspace() 函数第三个参数 (点数) 应该设置为 9。

代码语言:javascript复制
pd.cut(df['ext price'], bins=np.linspace(0, 200000, 9))

最后还有一个用于定义箱的方法,用 pd.interval_range()。该函数提供了很大的灵活性。例如,它可以设置边界区间的开闭,下例设置 close='left' 是说箱区间是左闭右开的。

代码语言:javascript复制
pd.interval_range(start=0, freq=10000, end=200000, closed='left')

看下 df 前五行的打印结果。需要注意的是,在使用 interval_range() 函数时,参数 labels 的设置被忽略了。

代码语言:javascript复制
interval_range = pd.interval_range(start=0, freq=10000, end=200000)
df['cut_ex2'] = pd.cut(df['ext price'], bins=interval_range, labels=[1,2,3])
df.head()

你学会用 cut 了吗?

Stay Tuned!

0 人点赞