📜  如何使用熊猫 cut() 和 qcut()?

📅  最后修改于: 2022-05-13 01:55:17.047000             🧑  作者: Mango

如何使用熊猫 cut() 和 qcut()?

Pandas是一个开源库,主要用于轻松直观地处理关系或标记数据。它提供了用于操作数值数据和时间序列的各种数据结构和操作。

在本教程中,我们将了解 pandas 的智能剪切和 qcut 功能。基本上,我们使用 cut 和 qcut 将数值列转换为分类列,也许是为了使其更适合机器学习模型(在数值列相当倾斜的情况下),或者只是为了更好地分析手头的数据。现在,与其脱口而出 cut 和 qcut 的技术定义,我们还不如看看这两个函数擅长什么以及如何使用它们。

我们将首先导入必要的数据操作库。

Python3
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt


Python3
df = pd.read_csv('cardekho.csv')
df.head()


Python3
# no missing values in the dataset
df.info()


Python3
df.loc[0, 'Year'] = np.nan
 
# these are the 'unique' years in
# the data
np.array(sorted(df.Year.unique()))


Python3
# right = True, by default
pd.cut(df.Year, bins=3, right=True).head()


Python3
pd.cut(df.Year, bins=3, right=False).head()


Python3
pd.cut(df.Year, bins=3,
       labels=['old', 'medium', 'new']).head()


Python3
df['Yr_cut'] = pd.cut(df.Year, bins=3,
                      labels=['old', 'medium', 'new'])
df.head()


Python3
pd.cut(df.Year, bins=3, labels=False).head()


Python3
df['Yr_cut'].value_counts()


Python3
df['Yr_cut'].value_counts().plot(kind='barh')
plt.show()


Python3
cut_series, cut_intervals = pd.cut(df.Year,
                                   bins=3,
                                   retbins=True)
 
print("Cut series:")
print(cut_series.head())
print()
print("Cut intervals: ", cut_intervals)


Python3
pd.cut(df.Year, bins=[2003,
                      2007,
                      2010,
                      2015,
                      2018],
       include_lowest=True).head()


Python3
pd.qcut(df.Year, q=5).head(7)


Python3
df['Yr_qcut'] = pd.qcut(df.Year, q=5,
                        labels=['oldest',
                                'not so old',
                                'medium',
                                'newer',
                                'latest'])
df.head()
 
df['Yr_qcut'].value_counts().plot(kind='barh')
plt.show()
 
qcut_series, qcut_intervals = pd.qcut(df.Year, q=5,
                                      labels=['oldest',
                                              'not so old',
                                              'medium',
                                              'newer',
                                              'latest'],
                                      retbins=True)
 
qcut_series.value_counts()


Python3
pd.qcut(df.Year,
        q=[0, 0.2, 0.4,
           0.6, 0.8, 1.0],
        labels=['oldest',
                'not so old',
                'medium',
                'newer',
                'latest']).value_counts()


Python3
qcut_intervals


Python3
# demonstrating with some random quantiles
pd.qcut(df.Year, q=[0,0.15,0.35,
                    0.51,0.78,1]).head()


Python3
pd.cut(df.Year,
       bins=pd.interval_range(start=2002.99,
                              end=2018,
                              periods=3)).head()


Python3
# basically dividing data into 3
# quantiles
pd.qcut(df.Kms_Driven,
        q=np.linspace(0,1,4)).head()


Python3
pd.qcut(df.Selling_Price,
        q=np.arange(0, 1.01, 0.25),
        labels=['inexpensive',
                'average',
                'high cost',
                'over budget']).head()


我们将使用 CarDekho 数据集,其中包含有关平台上列出的二手车的数据。你可以在这里找到数据集:

  • “年份”是购买汽车的年份。
  • “Selling_Price”是车主想要出售汽车的价格。
  • 'Present_Price' 是汽车当前的展厅前价格。
  • “车主”定义了该车在平台上架之前拥有的车主数量。

其余的列是不言自明的。

Python3

df = pd.read_csv('cardekho.csv')
df.head()

输出:

df_head

Python3

# no missing values in the dataset
df.info()

df_info

我们将注入一个缺失值,以更好地演示 cut 和 qcut 如何处理“不完美”数据集。

Python3

df.loc[0, 'Year'] = np.nan
 
# these are the 'unique' years in
# the data
np.array(sorted(df.Year.unique()))

输出:

unique_yrs

pd.cut()

我们可以通过两种方式使用“cut”函数:直接指定 bin 的数量并让 pandas 为我们计算等大小的 bin 的工作,或者我们可以根据需要手动指定 bin 边缘。

Python3

# right = True, by default
pd.cut(df.Year, bins=3, right=True).head()

输出:

切1

当我们指定 bins=3 时,pandas 看到数据中的年份范围是 2003 年到 2018 年,因此适当地将其分成 3 个等宽的 bins,每个 5 年:[(2002.985, 2008.0] < (2008.0, 2013.0] < ( 2013.0, 2018.0]。请注意,pandas 自动将第一个类别 (2002.985) 的下限值小于“年份”列 (2003) 中的最小值,以便将 2003 年包含在结果中好吧,因为你看到了,箱子的下限是开放式的,而上限是封闭式的(如右=真)

笔记: 您是否注意到 NaN 值在输出结果中也保留为 NaN?当我们指定 right=False 时,左边界现在是封闭的,而右边界是开放的。

Python3

pd.cut(df.Year, bins=3, right=False).head()

输出:

切割2

我们可以将 'labels' 参数指定为列表以便更好地分析,而不是返回间隔。

Python3

pd.cut(df.Year, bins=3,
       labels=['old', 'medium', 'new']).head()

输出:

切3

我们将把这个系列分配回原始数据框:

Python3

df['Yr_cut'] = pd.cut(df.Year, bins=3,
                      labels=['old', 'medium', 'new'])
df.head()

输出:

cut4df

如果我们指定labels=False,而不是bin标签,我们将得到bin的数字表示:这里,0代表旧的,1是中等的,2是新的。

Python3

pd.cut(df.Year, bins=3, labels=False).head()

输出:

切5

只是为了查看每个 bin 中有多少值:

Python3

df['Yr_cut'].value_counts()

输出:

切6

仅仅因为绘制图表取悦的人多于冒犯的人..

Python3

df['Yr_cut'].value_counts().plot(kind='barh')
plt.show()

输出:

切割条形图

现在,如果我们一次性需要 bin 间隔和离散序列,我们指定 retbins=True。 Pandas 将返回一个包含 2 个元素的元组:系列和 bin 间隔。我们将使用元组解包来获取两个输出。

Python3

cut_series, cut_intervals = pd.cut(df.Year,
                                   bins=3,
                                   retbins=True)
 
print("Cut series:")
print(cut_series.head())
print()
print("Cut intervals: ", cut_intervals)

输出:

切8

如前所述,我们还可以通过传入一个列表来手动指定 bin 边缘:

Python3

pd.cut(df.Year, bins=[2003,
                      2007,
                      2010,
                      2015,
                      2018],
       include_lowest=True).head()

输出:

切9

在这里,我们不得不提到 include_lowest=True。你能猜到为什么吗?因为默认情况下,'include_lowest' 参数设置为 False,因此当 pandas 看到我们传递的列表时,它将从计算中排除 2003。对于老鹰眼,我们也可以使用任何小于 2003 的值,例如 1999 或 2002 或 2002.255 等,并继续使用默认设置 include_lowest=False。

pd.qcut()

Qcut (quantile-cut) 与 cut 的不同之处在于,在 qcut 中,每个 bin 中的元素数量大致相同,但这将以不同大小的间隔宽度为代价。另一方面,在 cut 中,bin 边缘的大小相等(当我们指定 bins=3 时),每个 bin 或组中的元素数量是奇数。此外,当您确定区间范围和 bin 时,cut 很有用,

例如,如果对“年龄”列进行分箱,我们知道婴儿在 0 到 1 岁之间,1-12 岁是儿童,13-19 岁是青少年,20-60 岁是工人阶级成年人,60 岁以上是老年人。所以我们可以适当设置bins=[0, 1, 12, 19, 60, 140]和labels=['infant', 'kid', 'teenager', 'grownup', 'seniorCitizen']。在 qcut 中,当我们指定 q=5 时,我们告诉 pandas 将 Year 列分成 5 个相等的分位数,即 0-20%、20-40%、40-60%、60-80% 和 80-100% 桶/垃圾箱。

Python3

pd.qcut(df.Year, q=5).head(7)

输出:

qcut1

我们将把这个系列分配给数据框。

Python3

df['Yr_qcut'] = pd.qcut(df.Year, q=5,
                        labels=['oldest',
                                'not so old',
                                'medium',
                                'newer',
                                'latest'])
df.head()
 
df['Yr_qcut'].value_counts().plot(kind='barh')
plt.show()
 
qcut_series, qcut_intervals = pd.qcut(df.Year, q=5,
                                      labels=['oldest',
                                              'not so old',
                                              'medium',
                                              'newer',
                                              'latest'],
                                      retbins=True)
 
qcut_series.value_counts()

输出:

qcut2qcut3gqcut4

现在只是为了强调 q=5 确实意味着将值拆分为 5 个相等的分位数,每个分位数为 20%,我们将手动指定分位数,并获得与上述相同的 bin 分布。

Python3

pd.qcut(df.Year,
        q=[0, 0.2, 0.4,
           0.6, 0.8, 1.0],
        labels=['oldest',
                'not so old',
                'medium',
                'newer',
                'latest']).value_counts()

输出:

qcut5

我们现在将看到使用元组解包得到的 qcut 间隔数组:

Python3

qcut_intervals

输出:

qcut6

你看?在 qcut 中,bin 边缘的宽度不等,因为它容纳了每个桶中 20% 的值,因此它自己计算 bin 宽度以实现该目标。

Python3

# demonstrating with some random quantiles
pd.qcut(df.Year, q=[0,0.15,0.35,
                    0.51,0.78,1]).head()

输出:

qcut7

现在它将数据分箱到我们定制的 0-15%、15-35%、35-51%、51-78% 和 78-100% 的分位数列表中。
使用 qcut,我们正在回答“哪些数据点位于数据的前 15% 或 51-78 个百分位数范围内等问题。此外,我们还可以使用 pandas 的 interval_range 或 numpy 的 linspace 和 arange 来生成区间范围列表并将其分别作为 bin 和 q 参数提供给 cut 和 qcut。

Python3

pd.cut(df.Year,
       bins=pd.interval_range(start=2002.99,
                              end=2018,
                              periods=3)).head()

输出:

qcut8

使用 linspace:

Python3

# basically dividing data into 3
# quantiles
pd.qcut(df.Kms_Driven,
        q=np.linspace(0,1,4)).head()

输出:

qcut9

使用范围:

Python3

pd.qcut(df.Selling_Price,
        q=np.arange(0, 1.01, 0.25),
        labels=['inexpensive',
                'average',
                'high cost',
                'over budget']).head()

输出:

qcut10

有时当我们要求 pandas 为我们计算 bin 边缘时,您可能会遇到如下错误:
ValueError:Bin 边缘必须是唯一错误。这意味着在计算 bin 间隔时,pandas 发现两端的一些 bin 边缘是相同的,例如 (2014, 2014] 的间隔,因此会引发该错误。这通常发生在 bin 数量很大并且特定列的值范围很小。您可以通过传递 duplicates='drop' 的参数来消除此错误。