优衣库门店可视化与顾客拜访数据分组-Python数据分析项目

本文主要是介绍优衣库门店可视化与顾客拜访数据分组-Python数据分析项目,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 项目背景
    • 1 引言
    • 2 数据说明
  • 一、数据导入及预处理
    • 1 数据导入
    • 2 数据观察
      • 2.1 查看数据形状
      • 2.2 检查缺失值
      • 2.3 有无重复值
    • 3 数据预处理
      • 3.1 获取详细地址
      • 3.2 批量获取经纬度
        • 3.2.1 安装geopy包
        • 3.2.2 批量获取经纬度
  • 二、优衣库门店可视化
    • 1 数据获取
      • 1.1 读取地点数据
      • 1.2 筛选优衣库门店
    • 2 门店可视化
      • 2.1 带涟漪效果的散点图
      • 2.2 热力图
  • 三、拜访数据分组
    • 1 数据获取
    • 2 拜访数据分组
      • 2.1 KMeans分组
      • 2.2 输出分组结果
        • 2.2.1 分组结果
        • 2.2.2 中心点坐标
    • 3 K值调整
      • 3.1 The Elbow Method
      • 3.2 分组结果可视化
      • 3.3 聚类中心地址
    • 4 大屏展示
  • 总结与展望
    • 1 项目总结
    • 2 后期展望

项目背景

1 引言

在正文开始之前,大家可以先来考虑这样两个问题:

  1. 一家连锁企业在开设线下门店时会以哪些因素为参考呢?

  2. 在不同层次的城市应该分别开设多少家门店,门店位置如何选取,才能促其利润最大化呢?

在这里插入图片描述

这其实就是一个数据分析的过程,如果我们拥有相应城市的人口、GDP、人群分布、用户行为等数据,我们就可以使用尽可能科学的方法帮助我们计算出相应的商业中心。

那么,什么才是最科学的方法呢?下面就让我们一起来探索吧。

2 数据说明

该数据集是一份统计自在上海市热门地点活动的80人的拜访数据样例,包含顾客姓名、剩余拜访次数、地理位置等信息。

分为以下三个csv文件:

  • uniqlo.csv

  • uniqlo1.csv

  • uniqlo2.csv
    其中uniqlo2.csv是在uniqlo.csv的基础上添加了详细地址、经纬度等信息,具体方法分两步:

  1. 使用百度地图,根据地址信息查询其对应的详细地址;

  2. 使用经纬度查询工具,根据详细地址匹配对应位置的经纬度。
    为了说明地名数据的一般处理方法,下面我们使用不含详细地址及经纬度数据的这一份csv文件进行分析;大家也大家根据自己的情况考虑略过这部分操作,直接使用最后一份数据集进行后续的分析。

一、数据导入及预处理

1 数据导入

#读取不含经纬度信息的拜访数据import pandas as pddata = pd.read_csv('./uniqlo.csv')
data.head()

2 数据观察

2.1 查看数据形状

#查看数据形状data.shape

2.2 检查缺失值

#检查各列有无缺失值data.isnull().sum()

2.3 有无重复值

#检查各列独立元素的数目print('姓名数目为:',data['姓名'].nunique())
print('剩余拜访次数枚举值为:',data['剩余拜访次数'].unique())
print('地址数目为:',data['地址'].nunique())

姓名数目为: 80 剩余拜访次数枚举值为: [1 2 3] 地址数目为: 73

3 数据预处理

我们可以使用百度地图查询数据集中地址所对应的详细地址,继而使用Python支持的geopy工具包完成详细地址到经纬度的转换。

3.1 获取详细地址

由于数据量不大,我们此处使用百度地图手动处理;后续可以考虑调用适合的API来完成这一转换。
#读取含详细地址的数据data = pd.read_csv('./uniqlo1.csv')
data.head()

3.2 批量获取经纬度

3.2.1 安装geopy包
#### #安装geopy包,并指定清华源下载!pip install geopy -i https://pypi.tuna.tsinghua.edu.cn/simple/
print('-'*60)
print('geopy包安装完成!')
3.2.2 批量获取经纬度
# #根据详细地址获取经纬度# # 速度较慢,可直接读取经纬度解析完成的数据uniqlo2.csv# import warnings # warnings.filterwarnings('ignore')# from geopy.geocoders import Nominatim# geolocator = Nominatim(user_agent='Mozilla/5.0(Windows NT 10.0;WOW64)ApplewebKit/537.36(KHTML,like Gecko)Chrome/55.0.2883.75 Safari/537.36')# from geopy.extra.rate_limiter import RateLimiter# geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)# #获取location# data['location'] = data['详细地址'].apply(geocode)# #获取经度# data['经度'] = data['location'].apply(lambda loc: loc.longitude if loc else None)# #获取纬度# data['纬度'] = data['location'].apply(lambda loc: loc.latitude if loc else None)# print('经纬度解析完成!')# data.head()

二、优衣库门店可视化

1 数据获取

前面我们已经得到了带经纬度信息的优衣库门店数据,由于该数据中包含一些其他地点,因此我们需要对其进行相应的筛选;考虑到前一步得到的经纬度数据只到路道级别,不能保持原有数据的精确度,因此我们转而使用经经纬度解析工具解析后的这一份地点数据进行如下操作。

1.1 读取地点数据

#读取含经纬度的地点数据data2 = pd.read_csv('./uniqlo2.csv')
data2.head()

1.2 筛选优衣库门店

#根据地址字段筛选出含'优衣库'的数据行uniqlo = data2[data2['地址'].str.contains('优衣库')]
uniqlo.head()
#一共筛选出了多少条数据uniqlo.shape
#去重后的门店数uniqlo['地址'].nunique()
#40个门店分别是哪些uniqlo['地址'].unique()
#获取40个门店的名称及经纬度数据import numpy as npuniqlo = uniqlo.groupby('地址',as_index=False).agg({'剩余拜访次数':sum,'经度':np.mean,'纬度':np.mean})
uniqlo.head()

2 门店可视化

需安装包:pip install pyecharts -i https://pypi.tuna.tsinghua.edu.cn/simple/pip install echarts-countries-pypkg -i https://pypi.tuna.tsinghua.edu.cn/simple/pip install echarts-china-provinces-pypkg -i https://pypi.tuna.tsinghua.edu.cn/simple/pip install echarts-china-cities-pypkg -i https://pypi.tuna.tsinghua.edu.cn/simple/pip install echarts-china-counties-pypkg -i https://pypi.tuna.tsinghua.edu.cn/simple/pip install echarts-china-misc-pypkg -i https://pypi.tuna.tsinghua.edu.cn/simple/pip install echarts-united-kingdom-pypkg -i https://pypi.tuna.tsinghua.edu.cn/simple/

2.1 带涟漪效果的散点图

#使用pyecharts中的Geo类绘制散点图from pyecharts.charts import Geo
from pyecharts import options as opts
from pyecharts.globals import GeoTypecity = '上海'#实例化一个Geo类
geo = Geo()
#以上海市地图为底景
geo.add_schema(maptype=city)
# #添加地点坐标至坐标库中for i in range(40):geo.add_coordinate(uniqlo.iloc[i]['地址'],uniqlo.iloc[i]['经度'],uniqlo.iloc[i]['纬度'])data_pair = [(uniqlo.iloc[i]['地址'],int(uniqlo.iloc[i]['剩余拜访次数'])) for i in range(40)]
# 将数据添加到地图上geo.add('',data_pair,type_=GeoType.EFFECT_SCATTER, symbol_size=9)# 设置样式geo.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
#自定义分级
pieces = [{'min': 0, 'max': 1, 'label': '1', 'color': '#50A3BA'},{'min': 1, 'max': 2, 'label': '2', 'color': '#DD675E'},{'min': 2, 'max': 3, 'label': '3', 'color': '#E2C568'},{'min': 3, 'label': '4', 'color': '#3700A4'}
]
#是否自定义分段
geo.set_global_opts(visualmap_opts=opts.VisualMapOpts(is_piecewise=True, pieces=pieces),title_opts=opts.TitleOpts(title='上海市优衣库门店可视化'),)geo.render_notebook()

2.2 热力图

绘制热力图只需将GeoType参数为设置HEATMAP即可,具体展示如下:
city = '上海'#实例化一个Geo类
geo2 = Geo()
#以上海市地图为底景
geo2.add_schema(maptype=city)# #添加地点坐标至坐标库中for i in range(40):geo2.add_coordinate(uniqlo.iloc[i]['地址'],uniqlo.iloc[i]['经度'],uniqlo.iloc[i]['纬度'])data_pair = [(uniqlo.iloc[i]['地址'],int(uniqlo.iloc[i]['剩余拜访次数'])) for i in range(40)]# 将数据添加到地图上geo2.add('',data_pair,type_=GeoType.HEATMAP, symbol_size=5)# 设置样式geo2.set_series_opts(label_opts=opts.LabelOpts(is_show=False))#自定义分级
pieces = [{'min': 0, 'max': 1, 'label': '1', 'color': '#50A3BA'},{'min': 1, 'max': 2, 'label': '2', 'color': '#E2C568'},{'min': 2, 'max': 3, 'label': '3', 'color': '#DD675E'},{'min': 3, 'label': '4', 'color': '#DD0200'}
]
#是否自定义分段
geo2.set_global_opts(visualmap_opts=opts.VisualMapOpts(is_piecewise=True, pieces=pieces),title_opts=opts.TitleOpts(title='上海市优衣库门店可视化'),)geo2.render_notebook()

三、拜访数据分组

由于我们事先不知道将要把数据点分为哪些组,所以这是一个典型的无监督学习问题,以下我们将采用最常用的KMeans算法对拜访数据进行分组。

1 数据获取

#拜访地点数据获取visit = data2[['地址','经度','纬度']]
visit.head()

2 拜访数据分组

2.1 KMeans分组

这里简要介绍一下KMeans算法的步骤:

  1. 随机初始化k个聚类中心;

  2. 将n个待分类数据分配到距离它最近的聚类中心;

  3. 根据步骤2结果,重新计算新的聚类中心;

  4. 若达到最大迭代步数或两次迭代差小于设定的阈值则算法结束,否则重复步骤2。
    #使用KMeans算法将拜访数据分为8组

from sklearn.cluster import KMeanskmeans = KMeans(n_clusters=8,
init='k-means++',)X = visit[['经度','纬度']]
y = [0,1,2,3,4,5,6,7]
kmeans.fit(X,y)
y_pred = kmeans.predict(X)y_pred

2.2 输出分组结果

2.2.1 分组结果
#将各点分组结果添加到数据中visit_result = visit
visit_result['分组'] = y_predvisit_result.head()
2.2.2 中心点坐标
#中心点坐标center = kmeans.cluster_centers_
center
#获取中心点详细地址
import time
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0',timeout=5)
# 注意:建议访问速度不要太快,否则报timeout错误# for x,y in center:#     print(x,y)#     location = geolocator.reverse((y,x))#     print(location.address)#     time.sleep(1.5)

3 K值调整

3.1 The Elbow Method

由于这里没有事先对数据分成几组作出规定,因此我们有必要对K值进行调整,来找到一个能够使我们比较满意的分组结果;事实上,KMeans算法中K值的选取一直是业界比较关心的一个问题,这里我们采用最常用的 The Elbow Method(“肘方法”) 来选取一个恰当的K值。

#对不同的K值分别计算误差和from sklearn.cluster import KMeansinertia = []
for i in range(1,21):kmeans = KMeans(n_clusters=i,
init='k-means++')X = visit[['经度','纬度']]
kmeans.fit(X)
inertia.append(kmeans.inertia_)
inertia
#绘制误差和随K值的变化曲线图import matplotlib.pyplot as pltplt.style.use('fivethirtyeight')
plt.figure(figsize=(12,6))
plt.plot(range(1,11),inertia[0:10])plt.title('The Elbow Method')
plt.xlabel('K')
plt.ylabel('inertia')plt.show()

这里可以看到,当K<=10时,K=3是一个比较好的分组数目;为了解误差后续的变化趋势,我们看下K<=20时的结果。
#绘制误差和随K值的变化曲线图

在这里插入图片描述

plt.figure(figsize=(12,6))
plt.plot(range(1,21),inertia)plt.title('The Elbow Method')
plt.xlabel('K')
plt.ylabel('inertia')plt.show()

可以看到,K<=20时,拐点出现在K=9附近,但此处误差下降的速度并不明显,下面我们按照K=3来进行分组。

在这里插入图片描述

3.2 分组结果可视化

#使用KMeans算法将拜访数据分为3组from sklearn.cluster import KMeanskmeans = KMeans(n_clusters=3,
init='k-means++',)X = visit[['经度','纬度']]
kmeans.fit(X)
y_pred = kmeans.predict(X)y_pred
#K=3时拜访数据分组可视化from pyecharts.charts import Geo
from pyecharts import options as opts
from pyecharts.globals import GeoTypecity = '上海'#实例化一个Geo类
geo3 = Geo()
#以上海市地图为底景
geo3.add_schema(maptype=city)# #添加地点坐标至坐标库中for i in range(80):geo3.add_coordinate(visit.iloc[i]['地址'],visit.iloc[i]['经度'],visit.iloc[i]['纬度'])data_pair = [(visit.iloc[i]['地址'],int(y_pred[i])) for i in range(80)]# 将数据添加到地图上geo3.add('',data_pair,type_=GeoType.EFFECT_SCATTER, symbol_size=9)# 设置样式geo3.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
#自定义分级
pieces = [{'min': 0, 'max': 0, 'label': '1', 'color': '#50A3BA'},{'min': 0, 'max': 1, 'label': '2', 'color': '#DD0200'},{'min': 1, 'max': 2, 'label': '3', 'color': '#E2C568'}
]
#是否自定义分段
geo3.set_global_opts(visualmap_opts=opts.VisualMapOpts(is_piecewise=True, pieces=pieces),title_opts=opts.TitleOpts(title='上海市热门地点分组可视化'),)geo3.render_notebook()

在这里插入图片描述

3.3 聚类中心地址

#获取聚类中心坐标center_ = kmeans.cluster_centers_
center_
# 可以到 https://lbs.amap.com/tools/picker 输入经纬度121.48337518,31.23489423查看地图位置
#获取聚类中心点详细地址
# from geopy.geocoders import Nominatim
# geolocator = Nominatim(user_agent='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0',
#                       timeout=5)
# for i in range(3):
#     location = geolocator.reverse((center_[i][1],center_[i][0]))
#     print(location.address)
#     time.sleep(1.5)

4 大屏展示

from pyecharts.charts import Page
page = Page(layout=Page.DraggablePageLayout, page_title="大屏展示")page.add(geo,geo2,geo3)# 先保存到test.html 然后打开,拖拽图片自定义布局, 之后记得点击左上角“save config”对布局文件进行保存。# 会生成一个chart_config.json的文件,这其中包含了每个图表ID对应的布局位置page.render('test.html')# 然后运行下面这行代码。保存布局好的的仪表盘文件。page.save_resize_html('test.html', cfg_file='chart_config.json', dest='大屏展示1.html')

在这里插入图片描述

总结与展望

1 项目总结

本文展示了利用较少的数据量(主要是地点名称数据)也可以进行可视化分析与数据分组 等操作,其中包含了地点名称数据向地点详细地址、经纬度等信息的转换,以及根据经纬度数据对地点的聚类分组。
其中难点 便在于地点名称数据向地点详细地址、经纬度数据的转换,这个过程中我们可能要调用适当的API来完成这一转换,本文中我们使用的是geopy工具包中的地理位置编码与反编码等方法来实现。

在实际使用过程中,我们发现geopy包在对地理位置进行编码时对地点名称数据是有一定要求的,如“优衣库南京西路店”不能直接进行编码,于是我们统一使用“上海市(XX区)XX路”进行编码。
而由模糊地址向详细地址转换这一步暂时没有找到合适的API,这也是后期我们考虑优化的一个方向。
以上这种数据分组常见于寻找点群对应的城市中心,为门店选址提供依据等。

2 后期展望

下面我们来看这样一个实际场景:

  • 知乎某运营部门拟定对居住在北京,且粉丝数10w的大V举行一次线下交流会,考虑到北京全市面积较大且交通不便,决定将此次聚会分散至几个不同的地点进行,假设每个聚会地点人均消费相同,且已有每个人居住地点的数据,那么我们应当如何选取聚会地点,才能使每个人距离聚会地点尽可能近且每个聚会地人数尽可能多呢?

这就是一个典型的无监督数据分组问题,我们可以考虑使用上述的Kmeans算法来进行聚类。

  1. 由于本文所使用的数据集较少,其中所包含的优衣库门店并非全量数据,所以项目整体更偏向于一种分析思路的阐明,如果我们拥有比较多的数据,预期将会得到一个比较好的分组结果;

  2. 另外Kmeans算法本身存在一些如对异常值较为敏感、数据量大时算法比较复杂等缺点,因此我们也可以考虑使用基于密度的聚类方法对数据来进行分组;

  3. K值的确定:以上即使我们使用了“肘方法”,但由于误差的下降较为平缓,因此选取的K值比较难界定是否最优,实际情形中我们还需要根据具体情况进行处理;

  4. 在计算空间两点距离时我们直接使用了最常见的欧式距离,但这种近似仅适用于经纬度相差不大的点群,当点群之间经纬度相差较大时,我们应该转而使用球面距离。

这篇关于优衣库门店可视化与顾客拜访数据分组-Python数据分析项目的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/878330

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

Python Jupyter Notebook导包报错问题及解决

《PythonJupyterNotebook导包报错问题及解决》在conda环境中安装包后,JupyterNotebook导入时出现ImportError,可能是由于包版本不对应或版本太高,解决方... 目录问题解决方法重新安装Jupyter NoteBook 更改Kernel总结问题在conda上安装了

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相