新闻中心
信用卡客户划分
本文对信用卡客户数据进行聚类分析。先处理数据,删除无关ID,填补缺失值,对偏斜数据做对数转换。接着用PCA降维保留95%方差。通过肘部法和轮廓得分,选择2或3个聚类数,用KMeans聚类。结果显示,2类可分高低使用率客户,3类细分更优,能为营销策略提供依据。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

信用卡客户划分
作者: https://www.kaggle.com/muhammadzubairkhan92
译者: 我
本数据集所描述的问题要求我们根据数据集中提供的客户行为模式,提取出客户的细分市场,将企业的营销策略集中于某一细分市场。
In [17]import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as sns
加载数据
In [18]df = pd.read_csv('/home/aistudio/data/data82416/Credit Card Dataset for Clustering.csv')
In [19]
df.head()
CUST_ID BALANCE BALANCE_FREQUENCY PURCHASES ONEOFF_PURCHASES \
0 C10001 40.900749 0.818182 95.40 0.00
1 C10002 3202.467416 0.909091 0.00 0.00
2 C10003 2495.148862 1.000000 773.17 773.17
3 C10004 1666.670542 0.636364 1499.00 1499.00
4 C10005 817.714335 1.000000 16.00 16.00
INSTALLMENTS_PURCHASES CASH_ADVANCE PURCHASES_FREQUENCY \
0 95.4 0.000000 0.166667
1 0.0 6442.945483 0.000000
2 0.0 0.000000 1.000000
3 0.0 205.788017 0.083333
4 0.0 0.000000 0.083333
ONEOFF_PURCHASES_FREQUENCY PURCHASES_INSTALLMENTS_FREQUENCY \
0 0.000000 0.083333
1 0.000000 0.000000
2 1.000000 0.000000
3 0.083333 0.000000
4 0.083333 0.000000
CASH_ADVANCE_FREQUENCY CASH_ADVANCE_TRX PURCHASES_TRX CREDIT_LIMIT \
0 0.000000 0 2 1000.0
1 0.250000 4 0 7000.0
2 0.000000 0 12 7500.0
3 0.083333 1 1 7500.0
4 0.000000 0 1 1200.0
PAYMENTS MINIMUM_PAYMENTS PRC_FULL_PAYMENT TENURE
0 201.802084 139.509787 0.000000 12
1 4103.032597 1072.340217 0.222222 12
2 622.066742 627.284787 0.000000 12
3 0.000000 NaN 0.000000 12
4 678.334763 244.791237 0.000000 12
In [20]
df.describe()
BALANCE BALANCE_FREQUENCY PURCHASES ONEOFF_PURCHASES \
count 8950.000000 8950.000000 8950.000000 8950.000000
mean 1564.474828 0.877271 1003.204834 592.437371
std 2081.531879 0.236904 2136.634782 1659.887917
min 0.000000 0.000000 0.000000 0.000000
25% 128.281915 0.888889 39.635000 0.000000
50% 873.385231 1.000000 361.280000 38.000000
75% 2054.140036 1.000000 1110.130000 577.405000
max 19043.138560 1.000000 49039.570000 40761.250000
INSTALLMENTS_PURCHASES CASH_ADVANCE PURCHASES_FREQUENCY \
count 8950.000000 8950.000000 8950.000000
mean 411.067645 978.871112 0.490351
std 904.338115 2097.163877 0.401371
min 0.000000 0.000000 0.000000
25% 0.000000 0.000000 0.083333
50% 89.000000 0.000000 0.500000
75% 468.637500 1113.821139 0.916667
max 22500.000000 47137.211760 1.000000
ONEOFF_PURCHASES_FREQUENCY PURCHASES_INSTALLMENTS_FREQUENCY \
count 8950.000000 8950.000000
mean 0.202558 0.364437
std 0.298336 0.397448
min 0.000000 0.000000
25% 0.000000 0.000000
50% 0.083333 0.166667
75% 0.300000 0.750000
max 1.000000 1.000000
CASH_ADVANCE_FREQUENCY CASH_ADVANCE_TRX PURCHASES_TRX CREDIT_LIMIT \
count 8950.000000 8950.000000 8950.000000 8949.000000
mean 0.135144 3.248827 14.709832 4494.449450
std 0.200121 6.824647 24.857649 3638.815725
min 0.000000 0.000000 0.000000 50.000000
25% 0.000000 0.000000 1.000000 1600.000000
50% 0.000000 0.000000 7.000000 3000.000000
75% 0.222222 4.000000 17.000000 6500.000000
max 1.500000 123.000000 358.000000 30000.000000
PAYMENTS MINIMUM_PAYMENTS PRC_FULL_PAYMENT TENURE
count 8950.000000 8637.000000 8950.000000 8950.000000
mean 1733.143852 864.206542 0.153715 11.517318
std 2895.063757 2372.446607 0.292499 1.338331
min 0.000000 0.019163 0.000000 6.000000
25% 383.276166 169.123707 0.000000 12.000000
50% 856.901546 312.343947 0.000000 12.000000
75% 1901.134317 825.485459 0.142857 12.000000
max 50721.483360 76406.207520 1.000000 12.000000
In [21]
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 8950 entries, 0 to 8949 Data columns (total 18 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 CUST_ID 8950 non-null object 1 BALANCE 8950 non-null float64 2 BALANCE_FREQUENCY 8950 non-null float64 3 PURCHASES 8950 non-null float64 4 ONEOFF_PURCHASES 8950 non-null float64 5 INSTALLMENTS_PURCHASES 8950 non-null float64 6 CASH_ADVANCE 8950 non-null float64 7 PURCHASES_FREQUENCY 8950 non-null float64 8 ONEOFF_PURCHASES_FREQUENCY 8950 non-null float64 9 PURCHASES_INSTALLMENTS_FREQUENCY 8950 non-null float64 10 CASH_ADVANCE_FREQUENCY 8950 non-null float64 11 CASH_ADVANCE_TRX 8950 non-null int64 12 PURCHASES_TRX 8950 non-null int64 13 CREDIT_LIMIT 8949 non-null float64 14 PAYMENTS 8950 non-null float64 15 MINIMUM_PAYMENTS 8637 non-null float64 16 PRC_FULL_PAYMENT 8950 non-null float64 17 TENURE 8950 non-null int64 dtypes: float64(14), int64(3), object(1) memory usage: 1.2+ MBIn [22]
df.isna().mean()*100
CUST_ID 0.000000 BALANCE 0.000000 BALANCE_FREQUENCY 0.000000 PURCHASES 0.000000 ONEOFF_PURCHASES 0.000000 INSTALLMENTS_PURCHASES 0.000000 CASH_ADVANCE 0.000000 PURCHASES_FREQUENCY 0.000000 ONEOFF_PURCHASES_FREQUENCY 0.000000 PURCHASES_INSTALLMENTS_FREQUENCY 0.000000 CASH_ADVANCE_FREQUENCY 0.000000 CASH_ADVANCE_TRX 0.000000 PURCHASES_TRX 0.000000 CREDIT_LIMIT 0.011173 PAYMENTS 0.000000 MINIMUM_PAYMENTS 3.497207 PRC_FULL_PAYMENT 0.000000 TENURE 0.000000 dtype: float64
从报告中我们可以看到,大多数特征的平均值远远大于其中位数。这说明数据集中有一定的数据偏移,我们要看看是否可以做些什么。
我们还有一些Nan值要进行处理。
数据处理
客户ID似乎是每个客户的唯一ID,因此不会在确定集群中起到任何作用。
In [23]df.drop(['CUST_ID'], axis=1, inplace=True)
我们看到,信用额度功能只有0.01%的记录是Nan值,即这里只有1条记录有缺失值。所以我们不必费心去推算它。我们可以直接放弃它,再也不用考虑它了。
In [24]df.dropna(subset=['CREDIT_LIMIT'], inplace=True)
对于估算最低支付额的特征,我没有看到任何一列与这个特征有关的,可以帮助我们估算缺失记录的值。似乎这些值是随机缺失的,我们可以简单地使用中值来代替Nan值,因为最低支付额的分布是倾斜的,因此中值可以更好地估计这个特征的中心倾向。
In [25]df['MINIMUM_PAYMENTS'].fillna(df['MINIMUM_PAYMENTS'].median(), inplace=True)
如果我们不可视化,我们还算是数据科学家吗?
让我们来可视化一下我, 看看该数据集有多偏斜。
In [26]plt.figure(figsize=(20,35))for i, col in enumerate(df.columns): if df[col].dtype != 'object':
ax = plt.subplot(9, 2, i+1)
sns.kdeplot(df[col], ax=ax)
plt.xlabel(col)
plt.show()
<Figure size 1440x2520 with 17 Axes>
哇!!!有很多数据都是严重偏离的,而且它们是不同的。这符合我们预期,因为总会有一些客户有着非常高的交易量。
现在,这取决于我们的应用是否要处理数据集中的偏度问题。例如,如果我们想做聚类检测,在这种情况下,我们不想处理异常值,因为我们希望我们的模型能够检测到它们,并将它们分组。对于我们的应用,我正在寻找一个良好的可视化,所以我希望尽可能地处理偏度,因为它将帮助模型形成更好的聚类。
让我们看看我们是否可以在这方面做些什么。
In [27]cols = ['BALANCE', 'ONEOFF_PURCHASES', 'INSTALLMENTS_PURCHASES', 'CASH_ADVANCE', 'ONEOFF_PURCHASES_FREQUENCY','PURCHASES_INSTALLMENTS_FREQUENCY', 'CASH_ADVANCE_TRX', 'PURCHASES_TRX', 'CREDIT_LIMIT', 'PAYMENTS', 'MINIMUM_PAYMENTS', 'PRC_FULL_PAYMENT']In [28]
for col in cols:
df[col] = np.log(1 + df[col])
In [29]
plt.figure(figsize=(15,20))for i, col in enumerate(cols):
ax = plt.subplot(6, 2, i+1)
sns.kdeplot(df[col], ax=ax)
plt.show()
<Figure size 1080x1440 with 12 Axes>
我知道这可能看起来不像一个理想的分布,但它比刚才强一些了,作为数据科学家,我们的工作是尽可能地帮助我们的模型。
现在试着寻找一些关联性。
In [30]plt.figure(figsize=(12,12)) sns.heatmap(df.corr(), annot=True) plt.show()
<Figure size 864x864 with 2 Axes>
我们已经有了一些相关的功能。有很多方法可以处理这个问题。我们会继续进行维度降低,我们会把我们的数据降到低维。
我们会使用PCA来进行降维。
简单地解释一下PCA的工作原理,就是为数据集找到新的维度/轴,使它能解释最大的方差。这个轴就是第一个主成分。然后它选择另一个垂直于第一主成分的成分来解释最大方差。
所以对于上面的图像,如果我们把所有的点都投射在PCA一维上,那么这些点比在其他轴上投射更分散。这意味着PCA一维解释了最大的方差,因此它是我们的第一主成分。现在我们考虑垂直于这个分量的分量,由于这个数据是2维的,我们只有1个垂直于1维主成分的分量,它就成为我们的2维主成分。
注意:如果我们有第三维数据从屏幕上出来,那么我们将有2个垂直于第一主成分的成分,我们将不得不选择一个能解释两个主成分的最大方差。
一旦我们有了这些主成分,我们就可以选择我们希望拥有的成分数量,然后用这些主成分来表达我们的数据,从而减少维度。
所以我们在我们的案例中也是这样做的。我们将选择分量的数量,使我们的数据在较低的维度上能解释我们原始数据95%的方差。
In [31]from sklearn.decomposition import PCA pca = PCA(n_components=0.95) X_red = pca.fit_transform(df)
有了这些,我们就可以做我们一直想做的事情,即聚类。我们将使用Kmeans聚类算法从我们的数据集中额外提取信息集群。
模型培训
了解KMeans聚类算法的实际工作原理是相当有趣和直观的。
KMeans聚类是一种无监督的聚类算法,它将同一聚类中的相似数据聚在一起,形成k个聚类。结果我们得到了相似记录的群组,然后可以对这些记录进行相应的标记和操作。
html5+css3社交媒体用户个人资料信息卡片ui布局特效
一款html5+css3社交媒体用户个人资料信息卡片ui布局特效
24
查看详情
该算法是如何找到聚类的呢?
给定k个簇的数量,它首先选择k个随机点(可能不是数据集中的点)作为k个簇的中心点。
然后我们将每个点分配给最接近的中心点,形成k个簇。
一旦所有的点都被分配到一个簇中,我们就为每个簇计算新的中心点。
然后我们将点重新分配到最接近的中心点。
如果任何重新分配发生在步骤4,我们重复步骤3和4。如果没有发生重新分配,那么我们的模型已经准备好了,我们已经从我们的数据集中提取了k个聚类。
这个过程将在下图中解释。
但有一个问题。由于算法本身是以随机初始化k点开始的,所以很多事情都取决于初始化。由于我们现实世界的数据并不像上图中的数据那样泾渭分明,所以可能会发生这样的情况,即模型初始化k点的方式,我们最终可能会得到一个次优的解决方案。
为了避免这种情况,我们可以在每次迭代时用随机初始点多次运行算法。多次运行模型可以保证至少有一次我们避免了不好的初始化,达到最优解。Scikit learn实际上是对一个KMeans模型进行10次训练,我们可以通过if n_init超参数的帮助来控制。
为了衡量哪种模型在n次随机初始化中表现更好,我们可以使用模型innertia或wcss(Within Cluster Summation of Squares)。它测量的是每个点与其中心点的距离之和。所以我们希望紧凑的簇中的点尽可能的接近它的中心点。
另一种避免不良初始化的方法是使用KMeans++算法来初始化中心点。这个算法初始化中心点的方式是使所选择的中心点尽可能的相互接近,从而确保我们没有次优的解决方案。这个算法与前面的方法一起确保我们获得最佳的解决方案。Scikit learn使用KMeans++算法来初始化中心点,并由init超参数给出。
在这之前的整个讨论都是围绕着我们知道簇数n的假设进行的,因此n是这里最重要的超参数,必须将n初始化到合适的值。
为了得到n的值,我们不能使用innertia作为我们的度量,因为随着簇数的增加,innertia会不断增加。想一想,如果我们将n初始化为数据集中的点的数量,那么innertia将是最小的。
有一种方法可以绘制n与innertia的关系图,当我们绘制这个图时,我们可以发现一个肘部,在这个肘部之后,innertia会以更低的速度下降。如果我们可以用这个肘点对应的n作为我们的簇数。
另一种方法是计算轮廓分,它的计算公式为(b-a)/min(a,b),其中b->到最近集群实例的平均距离,a->到同一集群其他实例的平均距离。因此,如果到其他簇的点的平均距离减小,而到同一簇的点的平均距离增大,则剪影得分对模型进行惩罚。而如果到其他集群的点的平均距离增加,而到同一集群的点的平均距离减少,则奖励模型。因此我们可以选择一个剪影得分最高的模型。
Phew! 你还在这里?好了,理论够了。让我们在实践中看看这一切。
In [32]from sklearn.cluster import KMeans
kmeans_models = [KMeans(n_clusters=k, random_state=23).fit(X_red) for k in range (1, 10)]
innertia = [model.inertia_ for model in kmeans_models]
plt.plot(range(1, 10), innertia)
plt.title('Elbow method')
plt.xlabel('Number of Clusters')
plt.ylabel('WCSS')
plt.show()
<Figure size 432x288 with 1 Axes>
你看到那里的拐点了吗? 拐点好像是3、4左右 。我们用剪影分来看看哪个表现更好。
In [33]from sklearn.metrics import silhouette_score
silhoutte_scores = [silhouette_score(X_red, model.labels_) for model in kmeans_models[1:4]]
plt.plot(range(2,5), silhoutte_scores, "bo-")
plt.xticks([2, 3, 4])
plt.title('Silhoutte scores vs Number of clusters')
plt.xlabel('Number of clusters')
plt.ylabel('Silhoutte score')
plt.show()
<Figure size 432x288 with 1 Axes>
好吧,我们错
了n=2似乎比其他两个有更高的轮廓。所以, 我们将选择2作为我们的聚类数量。
模型评估和预测
In [34]from sklearn.metrics import silhouette_score
kmeans = KMeans(n_clusters=2, random_state=23)
kmeans.fit(X_red)print('Silhoutte score of our model is ' + str(silhouette_score(X_red, kmeans.labels_)))
Silhoutte score of our model is 0.8700455999561426
将标签作为簇索引分配给我们的数据集。
In [35]df['cluster_id'] = kmeans.labels_
将我们前面做的对数变换进行逆向变换,将结果在原比例上可视化。
In [36]for col in cols:
df[col] = np.exp(df[col])
In [37]
plt.figure(figsize=(10,6))
sns.scatterplot(data=df, x='ONEOFF_PURCHASES', y='PURCHASES', hue='cluster_id')
plt.title('Distribution of clusters based on One off purchases and total purchases')
plt.show()
<Figure size 720x432 with 1 Axes>In [38]
plt.figure(figsize=(10,6))
sns.scatterplot(data=df, x='CREDIT_LIMIT', y='PURCHASES', hue='cluster_id')
plt.title('Distribution of clusters based on Credit limit and total purchases')
plt.show()
<Figure size 720x432 with 1 Axes>
看上面2张图,好像我们的模型把信用卡使用率低的客户聚在了一个聚类,而把使用率较高的模型聚在了另一个聚类。很好!我们对资源进行相应的引导。
附带:
3似乎是一个拐点,所以我想知道3聚类的模型是什么样子.
In [39]kmeans = KMeans(n_clusters=3, random_state=23) kmeans.fit(X_red)
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
n_clusters=3, n_init=10, n_jobs=None, precompute_distances='auto',
random_state=23, tol=0.0001, verbose=0)
In [40]
df['cluster_id'] = kmeans.labels_In [41]
plt.figure(figsize=(10,6))
sns.scatterplot(data=df, x='ONEOFF_PURCHASES', y='PURCHASES', hue='cluster_id')
plt.title('Distribution of clusters based on One off purchases and total purchases')
plt.show()
<Figure size 720x432 with 1 Axes>In [42]
plt.figure(figsize=(10,6))
sns.scatterplot(data=df, x='CREDIT_LIMIT', y='PURCHASES', hue='cluster_id')
plt.title('Distribution of clusters based on Credit limit and total purchases')
plt.show()
<Figure size 720x432 with 1 Axes>
在我看来,这似乎是更好的聚类方法,因为它确实可以将使用信用卡次数多的上半数客户和使用次数少的客户区分开来。如果我们想根据信用卡的使用情况来指导我们的营销策略,这似乎是一个更可操作的结果。
以上就是信用卡客户划分的详细内容,更多请关注其它相关文章!
# ai
# css
# 表单
# 中文网
# 我们可以
# 中心点
# type
# fig
# udio
# igs
# red
# 临夏seo托管
# 黄州推广获客网站
# 黄岩关键词排名优化原理
# 雄安网站建设方案
# 网络营销及效果分析推广
# 微信推广t1营销吧tt团队很好
# 安丘网站建设作用
# 淘淘乐网站建设
# Google SEO教程书
# seo分析平台百度
# 在这
# 营销策略
# 是一个
# 都是
# 让我们
# 第一个
相关栏目:
【
行业资讯67740 】
【
技术百科0 】
【
网络运营39195 】
相关推荐:
主板如何禁用固态硬盘
华为如何面对苹果16
焊机上power指示灯亮是什么意思
shell如何执行sql脚本命令行
国标控制器单片机怎么接线
typescript是做什么用的
为什么ai老是说链接面板中缺少某些文件
有什么基础可以学typescript
春运抢票软件哪个最好用
如何查看固态硬盘分区
春运什么时候开始抢票
估值水平比较中市盈率E是什么意思
喇叭上标的power30w是什么意思
双十一的哪一天最优惠呢
市盈率为负值是什么意思
迅达热水器显示power是什么意思
ts什么意思
金色cmyk色值是多少
春运返程如何抢票成功
手机换电池要多少钱
360n6锁屏壁纸怎么设置
命令行如何打开打印机
建伍遥控器power是什么意思
单片机怎么加死循环
5r是多少钱
春运抢票哪里最火热
51单片机怎么连接端口
typescript有什么框架
春运抢票要用抢票软件吗
typescript参数怎么用
电瓶车的power是什么意思
如何安装台式机固态硬盘
power在充电器上是什么意思
nfc功能是什么意思怎么开启
市盈率ttm是什么意思
笔记本电脑多少钱
typescript怎么拼接
学typescript需要多久
typescript哪个最好
oracle中datediff函数怎么用 Oracle中DATEDIFF函数详解
如何使用批处理命令编译vc程序
单片机蓝牙怎么开启设备
多少毫安的充电宝可以带上飞机
什么网址不能域名解析
j*a中数组怎么传递
阿里云盘共享账户怎么用
考勤机power红灯是什么意思
三星固态硬盘如何保修
如何寻找和修复无法在 AI 中找到文件的问题
为什么youtube音乐打不开


2025-07-23
浏览次数:次
返回列表