优衣库门店可视化与顾客拜访数据分组-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

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p