cut与qcut区别
- 1、pd.cut()
- 2、pd.qcut()
- 3、cut与qcut区别
Pandas提供了智能剪贴功能:pd.cut()
与pd.qcut()
,它们通常用于更方便直观地处理关系型或标签型数据,将数据进行分箱/离散化
1、pd.cut()
我们可以通过两种方式使用cut()
函数:直接指定bin
的数量,让Pandas为我们计算等大小的bin
,或者我们可以按照自己的意愿手动指定bin
的边缘
在cut()
函数中,bin
边缘的间距大小是相等的,每个bin
或箱中的元素数量不均匀。例如,如果对年龄进行分箱,0-1岁是婴儿,1-12岁是孩子,12-18岁是青少年,18-60岁是成年人,60岁以上是老年人。所以我们可以设置:
bins=[0, 1, 12, 18, 60, 140]
labels=['infant', 'kid', 'teenager', 'grownup', 'senior citizen']
cut()
的API如下:
pd.cut(x,bins,right,labels,retbins,precision,include_lowest,duplicates,ordered)
其参数及说明如下:
- x:需要进行分箱的数据,1D数组或系列类型,如果数据存在NaN则报错
- bins:分箱的边界,如果是单个整数,则表示基于数据中的最小值和最大值生成等间距间隔;也可以是自定义边界值的列表或数组
- right:是否包含最右边的数值,默认为True(右闭)
- labels:分箱的标签,长度保持与分箱数一致
- retbins:是否显示分箱的边界值,默认为False。当
bins
为整数时设置True可以显示边界值 - precision:分箱边界的精度,默认3位小数
- include_lowest:是否包含最左边的数值,默认为False(左开)
- duplicates:默认为
raise
,如果分箱的边界不唯一,则引发ValueError;指定drop
则去重 - ordered:标签是否有序,默认为True,分类结果将被排序
以下是一个使用示例:
import pandas as pd
import numpy as np
# 数据准备
years = [2024, 2023, 2017, 2011, 2015, 2023, 2008, 2010]
df = pd.DataFrame(years, columns=['Year'])
基本使用如下:
# 左开右闭
print(pd.cut(df['Year'], bins=3, precision=0))
数据的年份范围是2008年到2024年(16个),当我们指定bins=3
时,Pandas将它切分成3个等宽的bin
,每个bin
5-6年。需要注意的是,Pandas会自动将第一类的下限值丢失精度,以确保将2008年也包括在结果中
# 左闭右闭
print(pd.cut(df['Year'], bins=3, include_lowest=True, precision=0))
可以将标签参数指定为一个列表,而不是获得间隔,以便更好地分析:
# 指定分类标签
df['Label'] = pd.cut(df['Year'], bins=3, labels=['Old', 'Medium', 'New'], precision=0)
print(df)
如果指定labels=False
,我们将得到bin
的数字表示(从0依次开始递增):
df['Label'] = pd.cut(df['Year'], bins=3, labels=False)
print(df)
查看每个分箱中的值数量:
print(df['Label'].value_counts().reset_index())
显示分箱的边界值:
# 我们可以指定retbins=True一次性获得bin区间和边界值离散的序列,此时方法返回一个二元组
cut_series, cut_intervals = pd.cut(df['Year'], bins=3, retbins=True, precision=0)
# bin区间
print(cut_series)
# 分箱的边界值
print(cut_intervals)
我们也可以通过给bins
参数传入一个列表来手动指定bin
的边缘:
# 自定义bin边缘
print(pd.cut(df['Year'], bins=[2008, 2010, 2020, 2024], include_lowest=True))
这里,我们设置了include_lowest=True
,默认情况下,它被设置为False,因此,当Pandas看到我们传递的列表时,它将把2008年排除在计算之外。因此,这里我们也可以使用任何小于2008的值
2、pd.qcut()
qcut()
函数(Quantile-Cut)与cut()
的关键区别在于,在qcut()
中,每个bin
中的元素数量将大致相同,但这将以不同大小的bin
区间宽度为代价
在qcut()
函数中,当我们指定q=5
时,我们告诉Pandas将数据列切成5个相等的量级,即0-20%,20-40%,40-60%,60-80%和80-100%桶/箱
qcut()
的API如下:
pd.qcut(x,q,labels,retbins,precision,duplicates)
其参数及说明如下:
- x:需要进行分箱的数据,1D数组或系列类型,如果数据存在NaN则保留
- q:分位数,例如4用于四分位,也可以指定为列表
[0,0.25,0.5,0.75,1]
- 其他参数:同
pd.cut()
给数据注入一个缺失值,我们看下qcut()
将如何处理一个包含NaN的数据集
# 添加NaN值
df.loc[0, 'Year'] = np.NaN
以下是一个使用示例:
# 左开右闭
print(pd.qcut(df['Year'], q=3))
你是否注意到,在输出结果中,NaN值也被保留为NaN?
指定分箱标签:
# 指定分箱标签
df['Label'] = pd.qcut(df['Year'], q=3, labels=['Old', 'Medium', 'New'])
print(df)
自定义分箱量级:
# 自定义分箱量级
print(pd.qcut(df['Year'], q=[0, 1 / 3, 2 / 3, 1]))
可以看到,分箱的边缘是不等宽的,因为它要容纳每个桶1/3的值,因此它要自己计算每个箱子的宽度来实现这一目标
3、cut与qcut区别
综上所述,现对cut()
与qcut()
方法的使用区别作如下总结:
cut()
分箱边缘是等间距的,因此,箱中的元素数量不均;qcut()
分箱箱中的元素数量是均匀的,因此,箱边缘不是等间距的cut()
分箱数据如果存在NaN则报错;qcut()
分箱则将存在的NaN保留
参考文章:https://geek-docs.com/pandas/pandas-tutorials/how-to-use-pandas-cut-and-qcut.html