In [1]:
#可以直接把这段代码贴进去
# 1. 首先将要使用的库全部进行导入,并设置程序运行路径
import os
os.chdir(r"C:\OneDrive\华莱士\Documents\office培训\PYTHON培训\第四周")
#设置路径,这里路径要改成自己的
import pandas as pd
import matplotlib.pyplot as plt
#处理数据及绘图
import warnings
warnings.filterwarnings('ignore')
#忽略警报
from bokeh.io import output_file
from bokeh.plotting import figure,show
from bokeh.models import ColumnDataSource
#交互式处理

In [2]:
#可以直接把这段代码贴进去
# 2. 数据导入并查看数据
# 这里有9万条上海餐饮点评打分数据(示例数据,并非真实数据)
df = pd.read_csv("上海餐饮数据.csv")
# 进行数据量以及标题信息的查看
#df.columns.tolist() # 第一行作为表头
print('总数据量为{}条'.format(len(df)))
df.head(15) # 查看前15条数据


总数据量为96398条
Out[2]:
类别 行政区 点评数 口味 环境 服务 人均消费 城市 Lng Lat
0 烧烤 浦东新区 176 8.0 8.6 7.9 124 上海市 121.967860 30.884477
1 美食 闵行区 2 6.1 6.5 6.3 0 上海市 121.967781 30.883818
2 粤菜 浦东新区 141 6.7 7.2 6.6 141 上海市 121.933142 30.893224
3 海鲜 浦东新区 76 7.2 7.2 7.3 148 上海市 121.926062 30.899868
4 烧烤 浦东新区 600 7.2 7.6 7.0 143 上海市 121.925877 30.901100
5 本菜 嘉定区 69 8.2 8.9 8.4 66 上海市 121.925866 30.906384
6 本菜 嘉定区 69 8.2 8.9 8.4 66 上海市 121.925866 30.906384
7 浙菜 浦东新区 21 7.0 7.0 6.9 146 上海市 121.923567 30.900464
8 海鲜 浦东新区 46 6.1 6.2 6.0 77 上海市 121.922624 30.899486
9 烧烤 浦东新区 4 6.9 6.9 6.9 0 上海市 121.922592 30.899010
10 浙菜 浦东新区 54 7.1 7.1 7.0 50 上海市 121.922503 30.901877
11 快餐 浦东新区 50 6.8 7.0 6.9 31 上海市 121.922031 30.898962
12 西餐 浦东新区 1321 8.5 8.3 7.8 70 上海市 121.921863 30.898837
13 西餐 浦东新区 1321 8.5 8.3 7.8 70 上海市 121.921863 30.898837
14 西餐 浦东新区 636 7.6 9.1 8.0 68 上海市 121.921295 30.898409

In [3]:
# 性价比 = (口味 + 环境 + 服务)/ 人均消费
# 代码如下,可以直接复制粘贴
# 3. 不同类别评价指标的选择
data_filter = df[['类别', '口味', '环境', '服务', '人均消费']]
data_filter['性价比'] = (data_filter['口味'] + data_filter['环境'] + data_filter['服务']) / data_filter['人均消费']
data_filter.dropna(inplace = True) # 去掉有空缺数据的行
data_filter = data_filter[(data_filter['口味']>0) & (data_filter['人均消费']>0)].reset_index()
del data_filter['index'] # 重新设置索引并删除原索引
data_filter.tail(15)


Out[3]:
类别 口味 环境 服务 人均消费 性价比
54874 浙菜 7.8 7.2 7.4 56 0.400000
54875 浙菜 7.4 7.1 7.3 106 0.205660
54876 浙菜 7.6 6.8 7.4 41 0.531707
54877 浙菜 9.1 7.7 8.8 62 0.412903
54878 海鲜 6.9 6.9 6.9 80 0.258750
54879 浙菜 7.2 7.1 7.4 68 0.319118
54880 海鲜 6.8 6.3 6.5 81 0.241975
54881 浙菜 6.9 6.6 6.6 80 0.251250
54882 浙菜 6.7 6.9 6.6 63 0.320635
54883 浙菜 7.7 7.0 7.4 76 0.290789
54884 浙菜 7.7 7.0 7.4 76 0.290789
54885 浙菜 7.5 7.0 7.2 58 0.374138
54886 亚菜 7.0 7.1 7.1 49 0.432653
54887 甜点 8.2 7.9 8.1 33 0.733333
54888 料理 7.2 7.1 7.0 25 0.852000

In [ ]:


In [7]:
# 5. 异常值数据的清洗工作

# 这里直接封装一个函数进行异常值的清洗,之后对于此类问题的处理可以直接进行函数的调用,而且处理各个字段的异常值应该分别进行处理,这样可以避免不同字段数据之间的影响

def f1(data,col):
    return data[['类别',col]]

data_kw = f1(data_filter,'口味') # 处理口味数据
data_rj = f1(data_filter,'人均消费') # 处理人均消费数据
data_xjb = f1(data_filter,'性价比') # 处理性价比数据

# 使用iqr进行异常值的清洗,今后可以直接进行函数的调用,只需要修改一下'类别'的信息即可
data_kw.tail(15) # 查看口味后15条数据


Out[7]:
类别 口味
54874 浙菜 7.8
54875 浙菜 7.4
54876 浙菜 7.6
54877 浙菜 9.1
54878 海鲜 6.9
54879 浙菜 7.2
54880 海鲜 6.8
54881 浙菜 6.9
54882 浙菜 6.7
54883 浙菜 7.7
54884 浙菜 7.7
54885 浙菜 7.5
54886 亚菜 7.0
54887 甜点 8.2
54888 料理 7.2

In [15]:
# 6. 数据标准化并排序

# 数据异常值处理完毕之后,标准化处理,还是一样直接封装函数,方便之后直接调用,依旧是对不同的数据进行标准化
# 所谓标准化,就是把数字减去最小值,除以最大值减最小值。
# 举例说明:口味的最大值为9.4,最小值为4.7。	黄浦区甜点	分数为8.2,标准化后为(8.2-4.7)/(9.4-4.7)=0.74

def f2(data,col):
    col_name = col + '_norm'
    data_gp = data.groupby('类别').mean()
    data_gp[col_name] = data_gp[col]
    data_gp.sort_values(by = col_name, inplace = True, ascending=False)
    return data_gp

data_kw_score = f2(data_kw,'口味')
data_rj_score = f2(data_rj,'人均消费')
data_xjb_score = f2(data_xjb,'性价比')

# 标准化的基本步骤:首先创建一个新字段(列)并命名,然后按照某个要求进行分组(为什么取均值可以想一下,这个要回顾上一步异常值处理后的数据的结果),接着按照分组后的数据使用'最大'/'最小'标准化,最后进行某个字段(一般是某个标准化后的字段)进行排序即可

data_kw_score.tail(15) # 查看后15条数据


Out[15]:
口味 口味_norm
类别
湾菜 7.607396 7.607396
烧烤 7.601964 7.601964
西菜 7.541071 7.541071
甜点 7.524346 7.524346
龙虾 7.508283 7.508283
面馆 7.505263 7.505263
浙菜 7.503864 7.503864
午茶 7.500000 7.500000
川菜 7.489197 7.489197
美食 7.469031 7.469031
助餐 7.394745 7.394745
快餐 7.361730 7.361730
湘菜 7.353606 7.353606
北菜 7.350125 7.350125
常菜 7.311667 7.311667

In [16]:
# 7. 数据合并与绘图前准备

# 经过异常值清洗和标准化处理,数据已经可以进行使用了。接着就是将分开处理的数据再合并在一起,因为存在三组数据,所以应该是两两合并(索引的标签都是餐馆的类型)

data_final_q1 = pd.merge(data_kw_score,data_rj_score,left_index=True,right_index=True)    # 首先合并口味、人均消费指标得分
data_final_q1 = pd.merge(data_final_q1,data_xjb_score,left_index=True,right_index=True)       # 接着合并性价比指标得分


# 使用bokeh绘图之前,需要将columns的数据设置为英文(index这一列的名称也要是英文),另外设置一下点的大小(size参数)

data_final_q1['size'] = data_final_q1['口味_norm'] * 40  # 添加size字段
data_final_q1.index.name = 'type'
data_final_q1.columns = ['kw','kw_norm','price','price_norm','xjb','xjb_norm','size']

data_final_q1.head(15)


Out[16]:
kw kw_norm price price_norm xjb xjb_norm size
type
素菜 8.021705 8.021705 78.658915 78.658915 0.497415 0.497415 320.868217
南菜 7.984874 7.984874 91.411765 91.411765 0.325731 0.325731 319.394958
本菜 7.959824 7.959824 155.530553 155.530553 0.287742 0.287742 318.392975
火锅 7.949428 7.949428 108.606867 108.606867 0.282454 0.282454 317.977111
亚菜 7.889937 7.889937 101.958071 101.958071 0.317688 0.317688 315.597484
蟹宴 7.873469 7.873469 237.945578 237.945578 0.180064 0.180064 314.938776
西餐 7.853583 7.853583 128.028395 128.028395 0.367199 0.367199 314.143326
疆菜 7.791221 7.791221 59.610687 59.610687 0.611234 0.611234 311.648855
州菜 7.772500 7.772500 71.125000 71.125000 0.441502 0.441502 310.900000
料理 7.770436 7.770436 76.457008 76.457008 0.403445 0.403445 310.817432
海鲜 7.693175 7.693175 129.958457 129.958457 0.269551 0.269551 307.727003
粤菜 7.635520 7.635520 129.714356 129.714356 0.333748 0.333748 305.420819
啡厅 7.630942 7.630942 46.251325 46.251325 0.601575 0.601575 305.237668
湾菜 7.607396 7.607396 84.819527 84.819527 0.474099 0.474099 304.295858
烧烤 7.601964 7.601964 80.174523 80.174523 0.434532 0.434532 304.078563

In [17]:
# 8. 出图

from bokeh.layouts import gridplot
from bokeh.models import HoverTool
from bokeh.models.annotations import BoxAnnotation

output_file('菜系类型.html')#输出文件
source = ColumnDataSource(data_final_q1)#创建数据
data_type = data_final_q1.index.tolist()#横坐标为index,要先转化为列表

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, 'box_select, reset, xwheel_zoom,pan,crosshair'])
result.circle(x = 'price', y = 'xjb_norm', source = source,
			line_color ='black',line_dash =[6,4], fill_alpha =0.6,size = 'size')

price_mid = BoxAnnotation(left = 40, right = 80, fill_alpha = 0.1, fill_color = 'navy')
result.add_layout(price_mid)#这里设置标记区


kw = figure(plot_width = 800,plot_height = 300,title = '口味得分',x_range = data_type,
               tools = [hover, 'box_select, reset, xwheel_zoom,pan,crosshair'])
kw.vbar(x = 'type', top = 'kw_norm', source = source, width = 0.8, alpha = 0.7,color = 'red')

price = figure(plot_width = 800,plot_height = 300,title = '人均消费得分',x_range = data_type,
               tools = [hover, 'box_select, reset, xwheel_zoom,pan,crosshair'])
price.vbar(x = 'type', top = 'price_norm', source = source, width = 0.8, alpha = 0.7,color = 'green')

p = gridplot([[result],[kw],[price]])#将三个图放在一个画布上
from bokeh.io import output_notebook
output_notebook() # 使用jupyter,加上这一行,可以直接在jupyter内显示
show(p)#一定要加show(p),否则不显示


Loading BokehJS ...

In [ ]: