作业要求:
1、从三个维度“口味”、“人均消费”、“性价比”对不同菜系进行比较,并筛选出可开店铺的餐饮类型
要求:
① 计算出三个维度的指标得分
② 评价方法:
口味 → 得分越高越好
性价比 → 得分越高越好
人均消费 → 价格适中即可
③ 制作散点图,x轴为“人均消费”,y轴为“性价比得分”,点的大小为“口味得分”
绘制柱状图,分别显示“口味得分”、“性价比得分”
- 建议用bokeh做图
实现代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
import os
os.chdir('C:/Users/Administrator/Desktop/项目07城市餐饮店铺选址分析')
#加载数据
data = pd.read_excel('上海餐饮数据.xlsx',sheetname=0)
#筛选出当前所需要的字段
data1 = data[['类别','口味','环境','服务','人均消费']]
#数据清洗,清除空值,为0的数据
data1.dropna(inplace=True)
data1 = data[(data['口味']>0) & (data1['人均消费']>0)]
#性价比指标
data1['性价比'] = (data1['口味']+data1['环境']+data1['服务']) / data1['人均消费']
#创建函数f1,制作箱型图查看异常值
def f1():
fig,axes = plt.subplots(1,3,figsize=(10,4))
data1.boxplot(column = ['口味'],ax=axes[0])
data1.boxplot(column = ['人均消费'],ax=axes[1])
data1.boxplot(column = ['性价比'],ax=axes[2])
#创建函数f2,清除异常值
def f2(data,col):
q1 = data[col].quantile(q=0.25)
q3 = data[col].quantile(q=0.75)
iqr = q3 - q1
t1 = q1 - 3*iqr
t2 = q3 + 3*iqr
return data[(data[col]>t1)&(data[col]<t2)][['类别',col]]
data_kw = f2(data1,'口味')
data_rj = f2(data1,'人均消费')
data_xjb = f2(data1,'性价比')
#创建函数f3,做标准化处理并排序
def f3(data,col):
col_name = col + '_norm'
data_gp = data.groupby('类别').mean()
data_gp[col_name] = (data_gp[col]-data_gp[col].min()) / (data_gp[col].max()-data_gp[col].min())
data_gp.sort_values(by = col_name,inplace=True,ascending=False)
return data_gp
data_kw_score = f3(data_kw,'口味')
data_rj_score = f3(data_rj,'人均消费')
data_xjb_score = f3(data_xjb,'性价比')
#数据合并
data_m1 = pd.merge(data_kw_score,data_rj_score,left_index=True,right_index=True)
data_m1 = pd.merge(data_m1,data_xjb_score,left_index=True,right_index=True)
#制作散点图,x轴为“人均消费”,y轴为“性价比得分”,点的大小为“口味得分”
from bokeh.plotting import figure,show,output_file
from bokeh.models.annotations import BoxAnnotation
from bokeh.models import HoverTool
from bokeh.models import ColumnDataSource
from bokeh.layouts import gridplot
output_file('pro7.html')
data_m1['size'] = data_m1['口味_norm'] * 40
#bokeh绘图时的横纵坐标最好是英文字段名,所以要更改列名
data_m1.index.name = 'type'
data_m1.columns = ['kw','kw_norm','price','price_norm','xjb','xjb_norm','size']
#创建ColumnDataSource数据
source = ColumnDataSource(data_m1)
#设置标签显示内容
hover = HoverTool(tooltips=[('餐饮类型','@type'),
('人均消费','@price'),
('性价比得分','@xjb_norm'),
('口味得分','@kw_norm')])
result = figure(plot_width=800,plot_height=300,
title = '餐饮得分情况',
x_axis_label = '人均消费',y_axis_label = '性价比得分',
tools = [hover,'reset,box_select,pan,xwheel_zoom,crosshair'])
result.circle(x = 'price',y = 'xjb_norm',size = 'size',
source = source,
line_color = 'black',
line_dash = [6,4],
line_alpha = 0.8,
fill_alpha = 0.6)
#设置人均消费中间价位区间
price_mid = BoxAnnotation(left=40,right=80,fill_alpha=0.2,fill_color='navy')
result.add_layout(price_mid)
result.ygrid.grid_line_dash = [6,4]
result.xgrid.grid_line_dash = [6,4]
#提取横坐标
lst_type = data_m1.index.tolist()
kw = figure(plot_width=800,plot_height=300,
title = '口味得分',
x_range = lst_type,
tools = [hover,'reset,box_select,pan,xwheel_zoom,crosshair'])
kw.vbar(x = 'type',top = 'kw_norm',source = source,
width = 0.8,alpha = 0.8,color = 'red')
kw.ygrid.grid_line_dash = [6,4]
kw.xgrid.grid_line_dash = [6,4]
price = figure(plot_width=800,plot_height=300,
title = '人均消费得分',
x_range = lst_type,
tools = [hover,'reset,box_select,pan,xwheel_zoom,crosshair'])
price.vbar(x = 'type',top = 'price_norm',source = source,
width = 0.8,alpha=0.8,color = 'green')
price.ygrid.grid_line_dash = [6,4]
price.xgrid.grid_line_dash = [6,4]
#组合图表
p = gridplot([[result],[kw],[price]])
show(p)
2、选择一个餐饮类型,在qgis中做将上海划分成格网空间,结合python辅助做空间指标评价,得到餐饮选址位置
- 课程这里以“素菜馆为例”
课程数据
① net_population.shp → 投影坐标系,上海1km²格网内的人口密度数据
② road.shp → 投影坐标系,上海道路数据
要求:
① 通过空间分析,分别计算每个格网内的几个指标:人口密度指标、道路密度指标、餐饮热度指标、同类竞品指标
② 评价方法:
人口密度指标 → 得分越高越好
道路密度指标 → 得分越高越好
餐饮热度指标 → 得分越高越好
同类竞品指标 → 得分越低越好
综合指标 = 人口密度指标0.4 + 餐饮热度指标0.3 + 道路密度指标0.2 +同类竞品指标0.1
③ 最后得到较好选址的网格位置的中心坐标,以及所属区域- 可以用bokeh制作散点图
实现步骤:
1.加载数据
2.以net_population.shp为网格基础数据,做空间统计
3.坐标参照系改为投影坐标系(上海市51N)
4.输入线条矢量图层road,计算线条总长(net01)
5.导入餐饮数据,另存为投影坐标系数据cy.shp
6.输入多边形矢量图层net01,输入点矢量图层cy,计算多边形内点的数量(net02)
7.打开cy.shp属性表,选中类别=素菜的元素,另存为sc.shp
8.输入多边形矢量图层net02,输入点矢量图层cy,计算多边形内点的个数(net03)
9.输入多边形矢量图层net03,导出多边形质心另存为point.shp
10.sc.shp另存为wgs84地理坐标系,打开属性表添加lng,lat字段
11.导出数据至excel,存为point.xlsx
12.在python中做指标标准化
df = pd.read_excel('point.xlsx',sheetname=1)
df.fillna(0,inplace=True)
df.columns = ['人口密度','道路长度','餐饮计数','素菜餐饮计数','lng','lat']
#指标统计
df['rkmd_norm'] = (df['人口密度']-df['人口密度'].min())/(df['人口密度'].max()-df['人口密度'].min())
df['cyrd_norm'] = (df['餐饮计数']-df['餐饮计数'].min())/(df['餐饮计数'].max()-df['餐饮计数'].min())
df['tljp_norm'] = (df['素菜餐饮计数'].max()-df['素菜餐饮计数'])/(df['素菜餐饮计数'].max()-df['素菜餐饮计数'].min())
df['dlmd_norm'] = (df['道路长度']-df['道路长度'].min())/(df['道路长度'].max()-df['道路长度'].min())
df['finall_score'] = df['rkmd_norm']*0.4+df['cyrd_norm']*0.3+df['tljp_norm']*0.1+df['dlmd_norm']*0.2
df_finall = df.sort_values(by='finall_score',ascending=False).reset_index()
#制作空间散点图
output_file('空间散点图.html')
df_finall['size'] = df_finall['finall_score'] * 20
df_finall['color'] = 'green'
df_finall['color'].iloc[:10] = 'red'
source = ColumnDataSource(df_finall)
hover = HoverTool(tooltips = [('经度','@lng'),
('纬度','@lat'),
('最终得分','@finall_score')])
p = figure(plot_width=800,plot_height=800,
title = '空间散点图',
tools = [hover,'box_select,reset,wheel_zoom,pan,crosshair'])
p.square(x = 'lng',y= 'lat',
size = 'size',
color = 'color',
source = source,
line_color = 'black',
fill_alpha = 0.5)
show(p)
项目总结:
该项目属于一个开店的问题,开店应该经营什么,应该在哪个地方开
该项目通过对上海餐饮数据的分析,筛选出可开店铺的餐饮类型并得到最佳的餐饮选址位置。
1.从问题1展示出的图表中可以看出在人均消费中间价位区间中素菜的口味评分是最高的,因此选择素菜为开店铺的餐饮类型。
2.从问题2展示出的图表中可以知道绿色部分即是素菜馆所在的位置,颜色越深的地方数量越多,表面该地段位置好,使用bokeh的wheel_zoom功能可以清楚的看到素菜top10所在位置(即红色所在位置)。
3.该项目中使用qgis起到空间辅助分析与处理的作用。
4.使用bokeh绘图而不是seaborn是因为bokeh能设置图表联动以及丰富的可视化交互。