如何使用 pandas 的cut函数进行数据分箱
在数据分析中,我们经常需要对连续的数据进行分箱(binning)或分段(segmentation)。Pandas 提供了一个非常方便的函数 cut
,可以帮助我们快速实现这个功能。cut
函数可以将连续的数据分割成几个不同的区间,每个区间是一个 bin。这在创建直方图(histogram)时非常有用,因为直方图就是通过将数据分割成多个 bin,然后统计每个 bin 中的数据点数量来绘制的。
本文将详细介绍如何使用 pandas 的 cut
函数进行数据分箱,并创建直方图。
1. pandas cut 函数
首先,我们来看一下 pandas 的 cut
函数的基本用法。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先创建了一个包含 1000 个随机数的 DataFrame。然后,我们使用 cut
函数将这些随机数分割成 10 个 bin。cut
函数会根据数据的最小值和最大值来确定 bin 的范围,然后将数据分配到相应的 bin 中。
2. 创建直方图
有了分箱后的数据,我们就可以创建直方图了。直方图是一种统计图表,用于展示数据的分布情况。在直方图中,横轴表示数据的范围,纵轴表示每个范围内的数据数量。
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 创建直方图
df['value_bin'].value_counts().sort_index().plot(kind='bar')
# 显示图表
plt.show()
Output:
在上面的代码中,我们首先使用 value_counts
函数统计每个 bin 中的数据数量。然后,我们使用 sort_index
函数将结果按照 bin 的范围进行排序。最后,我们使用 plot
函数创建直方图。
3. 自定义 bin 的范围
在使用 cut
函数时,我们还可以自定义 bin 的范围。例如,我们可以将数据分割成几个具有特定范围的 bin。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 定义 bin 的范围
bins = [-np.inf, -1, 0, 1, np.inf]
# 使用 cut 函数将数据分割成自定义的 bin
df['value_bin'] = pd.cut(df['value'], bins=bins)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先定义了 bin 的范围,然后使用 cut
函数将数据分割成这些自定义的 bin。
4. 添加 bin 的标签
我们还可以为每个 bin 添加标签,以便更好地理解数据。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 定义 bin 的标签
labels = ['Negative', 'Zero', 'Positive']
# 使用 cut 函数将数据分割成自定义的 bin,并添加标签
df['value_bin'] = pd.cut(df['value'], bins=bins, labels=labels)
# 输出结果
print(df.head())
在上面的代码中,我们首先定义了 bin 的标签,然后使用 cut
函数将数据分割成自定义的 bin,并添加了标签。
5. 计算每个 bin 的百分比
除了计算每个 bin 的数量,我们还可以计算每个 bin 的百分比。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 计算每个 bin 的百分比
df['value_bin'].value_counts(normalize=True)
print(df)
Output:
在上面的代码中,我们使用 value_counts
函数计算每个 bin 的数量,然后通过设置 normalize=True
参数,我们可以得到每个 bin 的百分比。
6. 使用 seaborn 创建直方图
除了使用 pandas 和 matplotlib,我们还可以使用 seaborn 库创建直方图。
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 使用 seaborn 创建直方图
sns.histplot(data=df, x='value', bins=10)
# 显示图表
plt.show()
Output:
在上面的代码中,我们使用 seaborn 的 histplot
函数创建了直方图。histplot
函数可以自动将数据分割成 bin,并创建直方图。
7. 使用 cut 函数处理日期数据
cut
函数不仅可以处理数值数据,还可以处理日期数据。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 创建一个包含随机日期的 DataFrame
df = pd.DataFrame(pd.date_range(start='2020-01-01', end='2020-12-31'), columns=['date'])
# 使用 cut 函数将日期分割成 12 个月
df['month'] = pd.cut(df['date'], bins=12)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先创建了一个包含 2020 年每一天日期的 DataFrame。然后,我们使用 cut
函数将这些日期分割成 12 个月。
8. 使用 cut 函数处理分类数据
cut
函数还可以处理分类数据。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 创建一个包含分类数据的 DataFrame
df = pd.DataFrame({'category': ['A', 'B', 'C', 'D', 'E'] * 200})
# 使用 cut 函数将分类数据分割成 5 个 bin
df['category_bin'] = pd.cut(df['category'].astype('category').cat.codes, bins=5)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先创建了一个包含分类数据的 DataFrame。然后,我们使用 cut
函数将这些分类数据分割成 5 个 bin。为了使用 cut
函数,我们需要先将分类数据转换为数值数据,我们可以使用 cat.codes
属性来实现这一点。
9. 使用 qcut 函数创建等频直方图
除了 cut
函数,pandas 还提供了 qcut
函数,可以创建等频直方图。等频直方图是将数据分割成包含相同数量数据的 bin。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 使用 qcut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.qcut(df['value'], q=10)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们使用 qcut
函数将数据分割成 10 个 bin。每个 bin 中的数据数量大致相同。
10. 使用 cut 函数处理缺失值
cut
函数可以处理包含缺失值的数据。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 创建一个包含缺失值的 DataFrame
df = pd.DataFrame({'value': np.random.randn(1000)})
df.loc[df.sample(frac=0.1).index, 'value'] = np.nan
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先创建了一个包含缺失值的 DataFrame。然后,我们使用 cut
函数将数据分割成 10 个 bin。cut
函数会忽略缺失值,只对非缺失值进行分割。
11. 使用 cut 函数处理有异常值的数据
cut
函数也可以处理包含异常值的数据。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 创建一个包含异常值的 DataFrame
df = pd.DataFrame({'value': np.random.randn(1000)})
df.loc[df.sample(frac=0.1).index, 'value'] = 100
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先创建了一个包含异常值的 DataFrame。然后,我们使用 cut
函数将数据分割成 10 个 bin。cut
函数会根据数据的最小值和最大值来确定 bin 的范围,因此,异常值会被分配到最后一个 bin。
12. 使用 cut 函数处理有重复值的数据
cut
函数还可以处理包含重复值的数据。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 创建一个包含重复值的 DataFrame
df = pd.DataFrame({'value': [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]})
# 使用 cut 函数将数据分割成 4 个 bin
df['value_bin'] = pd.cut(df['value'], bins=4)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先创建了一个包含重复值的 DataFrame。然后,我们使用 cut
函数将数据分割成 4 个 bin。cut
函数会根据数据的最小值和最大值来确定 bin 的范围,因此,重复值会被分配到相同的 bin。
13. 使用 cut 函数处理有序数据
cut
函数也可以处理有序数据。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 创建一个包含有序数据的 DataFrame
df = pd.DataFrame({'value': np.arange(1000)})
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先创建了一个包含有序数据的 DataFrame。然后,我们使用 cut
函数将数据分割成 10 个 bin。cut
函数会根据数据的最小值和最大值来确定 bin 的范围,因此,有序数据会被均匀地分配到各个 bin。
14. 使用 cut 函数处理无序数据
cut
函数还可以处理无序数据。
import pandas as pd
import numpy as np
# 创建一个包含随机数的 DataFrame
df = pd.DataFrame(np.random.randn(1000), columns=['value'])
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 创建一个包含无序数据的 DataFrame
df = pd.DataFrame({'value': np.random.permutation(1000)})
# 使用 cut 函数将数据分割成 10 个 bin
df['value_bin'] = pd.cut(df['value'], bins=10)
# 输出结果
print(df.head())
Output:
在上面的代码中,我们首先创建了一个包含无序数据的 DataFrame。然后,我们使用 cut
函数将数据分割成 10 个 bin。cut
函数会根据数据的最小值和最大值来确定 bin 的范围,因此,无序数据会被均匀地分配到各个 bin。
总结起来,pandas 的 cut
函数是一个非常强大的工具,可以帮助我们快速地将连续的数据分割成几个不同的区间,这在创建直方图时非常有用。