Python大数据分析6:案例-什么样的顾客买的更多?

这里我们使用一个著名的数据集合,是kaggle网站提供的某超市销售记录,共有近54万条记录,

每条记录都给出了在黑色星期五(国外著名的年终购物节)购买商品的顾客信息,其中含有诸如年龄、职业、地区和购物额等基本信息,我们不妨利用这个数据来看看可视化分析的效果。

首先,我们加载数据集,并统计不同年龄段上购物额的平均值:

# coding:utf-8

import pandas as pd

frame = pd.read_csv(‘C:\\temp\\BlackFriday.csv’)

results = frame[[‘Purchase’]].groupby(frame[‘Age’]).mean()

print(results)

直接看结果,我们可以发现随着年龄的增长,购物额总体呈现不断上升的趋势。

使用散点图,可以更好的看出对应趋势:

plt.scatter(results[‘Purchase’], results.index, c=results[‘Purchase’], s=results[‘Purchase’])

plt.colorbar()

plt.show()

这里还故意使用颜色和点的大小来表达购物额的大小。

我们再看看居住时长的影响。

results = frame[[‘Purchase’]].groupby(frame[‘Stay_In_Current_City_Years’]).mean()

plt.scatter(results[‘Purchase’], results.index, c=results[‘Purchase’], s=results[‘Purchase’])

plt.colorbar()

plt.show()

也呈现出类似的效果。

使用三维散点图也可以进一步综合来看:

ax = plt.subplot(projection=’3d’)

ax.scatter(results[‘Purchase’], results.index.codes[0], results.index.codes[1],

           color=cm.ScalarMappable().to_rgba(results[‘Purchase’]), s=200)

sm = plt.cm.ScalarMappable(norm=plt.Normalize(vmin=results[‘Purchase’].min(), vmax=results[‘Purchase’].max()))

plt.colorbar(sm)

plt.show()

发现确实购物额会随着年龄段和居住时长的增长而增多。

这样做没有问题,但是这种分析过于麻烦,需要自己一个个的去分析总结。而且这里的问题其实表现为一种数据相关性问题,就是用户什么样的特征属性与购物额有重要的联系?通过分组查询,确实能在总体上看出数据之间的联系,但是一般要求这种数据是数值类型,如果是一般的文本描述,则分组查询就难以利用分组条件属性的数值变化关系看出来对应的统计属性的变化相关性。

因此,我们可以尝试使用更为专业的数据相关度分析方法:

DataFrame的corr函数可以返回数据相关度,默认方法为皮尔逊系数,该数值为一个-1到1之间的小数,越靠近1,说明正相关,越靠近-1说明负相关,靠近0说明不相关。

pd.set_option(‘display.max_columns’, None)

print(frame.corr())

为了看清全部列,我们增加了显示全部列的设置。从结果可以看出,自己列和自己列肯定是完全相关,没有意义。其中最高的是产品类别1和产品类别2、产品类别3和产品类别2,这两个数据如果借助分组查询来分析,由于相关数值都是都是类别标签代码,数值之间的大小不能反映任何联系,只用于区分,因此很难直接看出。

不过,我们刚才计算的年龄和居住时长却没有出现。

原因在于这两个列都不是数值型,一个是年龄范围的表示,一个部分记录是非整数型。因此我们必须对数据进行必要的处理。

我们先看年龄列。为了简单处理,这一列我们可以只取数据的第一个数字,既能反映年龄区间,也是整数。至于如何取第一个字符,其实很简单,

print(‘Age'[0])

这就表示取A这个第一个字符,但是对于DataFrame来说,这样写会被误解为行的表示:

print(frame[‘Age’][0])

因此我们采用了apply方法:

print(frame[‘Age’].apply(lambda x: x[0]))

大家可能觉得apply里面这个看不懂,这其实是个匿名函数,大家也虚无了解细节,只需了解通过这种写法,每个Age数据被apply函数通过x传递到[0]上,形成正确的表示。

我们再看看居住时长,只需将4+这种表示的全部映射为4即可。

frame.loc[frame[‘Stay_In_Current_City_Years’] == ‘4+’, ‘Stay_In_Current_City_Years’] = 4

print(frame)

这其实是个查询更新问题,即找到所有居住时长为4+的记录,并将这些记录的居住时长更新为4。

最终我们就可以完成更多列的相关度分析了。

# coding:utf-8
import pandas as pd

frame = pd.read_csv('C:\\temp\\BlackFriday.csv')
pd.set_option('display.max_columns', None)
frame['Age'] = frame['Age'].apply(lambda x: x[0])
frame.loc[frame['Stay_In_Current_City_Years'] == '4+', 'Stay_In_Current_City_Years'] = 4
frame['Age'] = frame['Age'].astype(int)
frame['Stay_In_Current_City_Years'] = frame['Stay_In_Current_City_Years'].astype(int)
print(frame.corr())

这里要注意一个问题,必须将现有的年龄列和居住时长列转换为整数,因为本来是字符型,即使更新为数字,列类型仍然为字符类型,所以我们使用了astype变成了整数。

从结果可以看出,年龄和居住时长确实相关,但是其实不是最相关的,职业最为相关。当然,总体相关度都比较弱。

不过,这个数据非常大,因此我们接下来借助于可视化方法来展示下。

import seaborn as sns

sns.heatmap(frame.corr())

plt.show()

这里我们使用一个seaborn库,该库依然还需先外部导入项目,同时它不是独立使用的库,要结合matplotlib库。用法很简单,先在代码中导入库,调用heatmap生成热力图,这是最适合显示数据相关度的可视化图。

从中可以看出,从整体来看,上述类别之间都存在较高的相关性,已婚状态和年龄呈现明显相关性,当然这是常识。但是年龄列确实与很多其他列都存在较为明显的相关性。而且,我们还注意到产品类别1和产品类别2和购物额反而呈现一定的负相关,也就是购买了这两类商品的用户往往购物额更低。

seaborn提供的功能非常强大,使用却很简单,我们再看看分层相关性热力图。

sns.clustermap(frame.corr())

plt.show()

这里,它不仅进行了相关度热力图的绘制,而且还给出了一种特征的聚类,看的出来,不同的属性特征可以根据不同的相似程度归入到一个类别下。

seaborn甚至还能提供一些更为基础的分析功能:

sns.countplot(frame[‘Age’])

plt.show()

比如可以显示属性特征各个数值及其个数统计,使用方法更为简单,无需我们主动分组。

效果类似于柱状图,大家可以多了解。不过,如果数据比较大,部分练习可能速度较慢,大家需要安心等待。

发表评论

电子邮件地址不会被公开。 必填项已用*标注