北京东城区美食分析
一 绪论¶
分析背景:美食荟萃的北京东城区,哪家餐厅最热门,哪家餐厅口味好,哪种菜系最受欢迎,哪个区域餐厅最多,人均消费与区域、菜系的关系?Python分析大众点评数据,我们一一解答这些问题。
数据来源:八爪鱼爬取大众点评东城区美食。
主要结论:1 热门餐厅: 金鼎轩南北菜人气最高,比萨到PizzoNow口味最好;
2 大众口味:火锅、西餐、日本菜、北京菜最热门;
3 繁华商圈:王府井/东单餐厅数量最多;
4 人均消费:75%的餐厅人均消费小于130元,私房菜人均消费最高,马桥/三里元商圈的饭贵。
二 数据预处理¶
In [4]:
import numpy as np
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
1 读取数据
In [5]:
df=pd.read_csv(U'F:/analyst_example/beijing
delicious1.csv',sep=';',encoding='gbk')
df.head()
Out[5]:
|
|
shop_name |
comments |
average_money |
cooking_style |
region |
stress |
taste |
environment |
service |
branch |
|
0 |
比萨到PizzaNow(安定门外店) |
1698\n 条点评 |
60.0 |
西餐 |
安定门 |
安定门外大街甲82号隆和写字楼1层8号 |
9.3 |
9.3 |
9.3 |
分店 |
|
1 |
四季民福烤鸭店(故宫店) |
8449\n 条点评 |
150.0 |
北京菜 |
王府井/东单 |
南池子大街11号故宫东门旁 |
9.2 |
9.3 |
9.3 |
分店 |
|
2 |
捞王锅物料理(apm店) |
392\n 条点评 |
139.0 |
火锅 |
王府井/东单 |
王府井大街138号apm5层532-535号 |
9.2 |
9.3 |
9.3 |
NaN |
|
3 |
COMBAL盉 by TIAGO(中粮广场店) |
74\n 条点评 |
403.0 |
西餐 |
王府井/东单 |
建国门内大街8号中粮广场C座1层 |
9.2 |
9.2 |
9.3 |
NaN |
|
4 |
DeepRed深红 |
321\n 条点评 |
594.0 |
创意菜 |
东四十条 |
东四十三条50号 |
9.2 |
9.4 |
9.3 |
NaN |
2 观察数据
-数据为DataFrame格式,共有735行/10列;
-average_money,taste,environment,service为float类型,其他为object(可以存储任意类型数据);
-average_money列存在4个缺失值;branch列存在417个缺失值,表明417个餐厅不是分店。
In [6]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 735 entries, 0 to 734
Data columns (total 10 columns):
shop_name 735 non-null object
comments 735 non-null object
average_money 731 non-null float64
cooking_style 735 non-null object
region 735 non-null object
stress 735 non-null object
taste 735 non-null float64
environment 735 non-null float64
service 735 non-null float64
branch 318 non-null object
dtypes: float64(4), object(6)
memory usage: 57.5+ KB
In [7]:
df['average_money'].isnull().value_counts()
Out[7]:
False 731
True 4
Name: average_money, dtype: int64
In [8]:
df['branch'].isnull().value_counts()
Out[8]:
True 417
False 318
Name: branch, dtype: int64
三 数据清洗¶
1 删除重复值
-删重后数据仍有735行,故无重复值;
In [9]:
df_duplicates=df.drop_duplicates()
df_duplicates.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 735 entries, 0 to 734
Data columns (total 10 columns):
shop_name 735 non-null object
comments 735 non-null object
average_money 731 non-null float64
cooking_style 735 non-null object
region 735 non-null object
stress 735 non-null object
taste 735 non-null float64
environment 735 non-null float64
service 735 non-null float64
branch 318 non-null object
dtypes: float64(4), object(6)
memory usage: 63.2+ KB
2 缺失值处理
-branch 列缺失值填充'无':branch缺失值为不是分店的店铺,故填充无。
In [10]:
df_duplicates['branch']=df_duplicates['branch'].fillna('无')
df_duplicates['branch'].head()
Out[10]:
0 分店
1 分店
2 无
3 无
4 无
Name: branch, dtype: object
-average_money 列删除缺失值:缺失值数量占比小(4/735),且人均消费与多种因素有关,故删除缺失值。
In [11]:
df1=df_duplicates.dropna()
df1.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 731 entries, 0 to 734
Data columns (total 10 columns):
shop_name 731 non-null object
comments 731 non-null object
average_money 731 non-null float64
cooking_style 731 non-null object
region 731 non-null object
stress 731 non-null object
taste 731 non-null float64
environment 731 non-null float64
service 731 non-null float64
branch 731 non-null object
dtypes: float64(4), object(6)
memory usage: 62.8+ KB
3 列处理
-comments列中提取点评数值
首先查找\n所在的位置;然后提取换行符前面的点评数量,为comment1列;最后修改comments1数据类型为int型。
In [12]:
df1.head()
Out[12]:
|
|
shop_name |
comments |
average_money |
cooking_style |
region |
stress |
taste |
environment |
service |
branch |
|
0 |
比萨到PizzaNow(安定门外店) |
1698\n 条点评 |
60.0 |
西餐 |
安定门 |
安定门外大街甲82号隆和写字楼1层8号 |
9.3 |
9.3 |
9.3 |
分店 |
|
1 |
四季民福烤鸭店(故宫店) |
8449\n 条点评 |
150.0 |
北京菜 |
王府井/东单 |
南池子大街11号故宫东门旁 |
9.2 |
9.3 |
9.3 |
分店 |
|
2 |
捞王锅物料理(apm店) |
392\n 条点评 |
139.0 |
火锅 |
王府井/东单 |
王府井大街138号apm5层532-535号 |
9.2 |
9.3 |
9.3 |
无 |
|
3 |
COMBAL盉 by TIAGO(中粮广场店) |
74\n 条点评 |
403.0 |
西餐 |
王府井/东单 |
建国门内大街8号中粮广场C座1层 |
9.2 |
9.2 |
9.3 |
无 |
|
4 |
DeepRed深红 |
321\n 条点评 |
594.0 |
创意菜 |
东四十条 |
东四十三条50号 |
9.2 |
9.4 |
9.3 |
无 |
In [13]:
def cut_word(word):
position=word.find('\n')
comments1=word[ :position]
return comments1
In [14]:
df1['comments1']=df1['comments'].apply(cut_word).astype('int')
df1['comments1'].head()
Out[14]:
0 1698
1 8449
2 392
3 74
4 321
Name: comments1, dtype: int32
4 新建df_clean 存储清理后的数据
In [15]:
df_clean=df1[['shop_name','comments1','average_money','cooking_style','region','stress','taste','environment','service','branch']]
df_clean.head()
Out[15]:
|
|
shop_name |
comments1 |
average_money |
cooking_style |
region |
stress |
taste |
environment |
service |
branch |
|
0 |
比萨到PizzaNow(安定门外店) |
1698 |
60.0 |
西餐 |
安定门 |
安定门外大街甲82号隆和写字楼1层8号 |
9.3 |
9.3 |
9.3 |
分店 |
|
1 |
四季民福烤鸭店(故宫店) |
8449 |
150.0 |
北京菜 |
王府井/东单 |
南池子大街11号故宫东门旁 |
9.2 |
9.3 |
9.3 |
分店 |
|
2 |
捞王锅物料理(apm店) |
392 |
139.0 |
火锅 |
王府井/东单 |
王府井大街138号apm5层532-535号 |
9.2 |
9.3 |
9.3 |
无 |
|
3 |
COMBAL盉 by TIAGO(中粮广场店) |
74 |
403.0 |
西餐 |
王府井/东单 |
建国门内大街8号中粮广场C座1层 |
9.2 |
9.2 |
9.3 |
无 |
|
4 |
DeepRed深红 |
321 |
594.0 |
创意菜 |
东四十条 |
东四十三条50号 |
9.2 |
9.4 |
9.3 |
无 |
In [16]:
df_clean.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 731 entries, 0 to 734
Data columns (total 10 columns):
shop_name 731 non-null object
comments1 731 non-null int32
average_money 731 non-null float64
cooking_style 731 non-null object
region 731 non-null object
stress 731 non-null object
taste 731 non-null float64
environment 731 non-null float64
service 731 non-null float64
branch 731 non-null object
dtypes: float64(4), int32(1), object(5)
memory usage: 60.0+ KB
四 数据分析¶
1 热门餐厅
-评论数前五的餐厅
In [17]:
df_clean.sort(columns='comments1',ascending=False).head()
Out[17]:
|
|
shop_name |
comments1 |
average_money |
cooking_style |
region |
stress |
taste |
environment |
service |
branch |
|
421 |
金鼎轩南北菜(地坛店) |
27816 |
74.0 |
粤菜 |
安定门 |
和平里西街77号 |
8.4 |
7.6 |
7.4 |
分店 |
|
345 |
胡大饭馆(簋街总店) |
12570 |
148.0 |
川菜 |
北新桥/簋街 |
东直门内大街233号 |
8.8 |
8.1 |
8.0 |
分店 |
|
103 |
温野菜日式火锅 |
12396 |
145.0 |
日本菜 |
东直门 |
新中街甲3号蜂巢剧场B1层 |
9.0 |
9.1 |
8.8 |
无 |
|
420 |
花家怡园(四合院总店) |
11589 |
153.0 |
北京菜 |
北新桥/簋街 |
东直门内大街235号,簋街西边 |
8.0 |
8.8 |
7.9 |
分店 |
|
126 |
西贝莜面村(北京apm店) |
11547 |
90.0 |
西北菜 |
王府井/东单 |
王府井大街138号北京apmA区5层509 |
9.0 |
9.1 |
9.1 |
分店 |
-taste评分前五的餐厅
In [18]:
df_clean.sort(columns='taste',ascending=False).head()
Out[18]:
|
|
shop_name |
comments1 |
average_money |
cooking_style |
region |
stress |
taste |
environment |
service |
branch |
|
0 |
比萨到PizzaNow(安定门外店) |
1698 |
60.0 |
西餐 |
安定门 |
安定门外大街甲82号隆和写字楼1层8号 |
9.3 |
9.3 |
9.3 |
分店 |
|
5 |
老诚一锅(东四十条店) |
1603 |
88.0 |
火锅 |
东四十条 |
东直门南小街139号 |
9.3 |
9.3 |
9.3 |
分店 |
|
13 |
然寿司(钱粮胡同店) |
552 |
1500.0 |
日本菜 |
东四 |
钱粮胡同东口16-2号 |
9.2 |
9.1 |
9.1 |
分店 |
|
199 |
垚焱馕坑烤肉 |
440 |
86.0 |
烧烤 |
北新桥/簋街 |
北新桥三条67号 |
9.2 |
7.5 |
9.1 |
无 |
|
82 |
亮健容天土锅羊蝎子(净土胡同总... |
1992 |
78.0 |
火锅 |
安定门 |
安定门内大街净土胡同8号 |
9.2 |
8.2 |
8.9 |
分店 |
2 热门菜系——火锅,西餐,日本菜,北京菜评论数、餐厅数量TOP 5中。
-各菜系按餐厅数量分类汇总,排名前五的为火锅、西餐、日本菜、面包甜点、北京菜。
-热门菜系(top 10)中日本菜、粤菜、西餐人均消费超过150元,其他菜系人均小于150元。
In [70]:
df_clean.cooking_style.value_counts().head()
Out[70]:
火锅 125
西餐 87
日本菜 66
面包甜点 55
北京菜 53
Name: cooking_style, dtype: int64
In [72]:
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
ax=df_clean.groupby('cooking_style').agg({'shop_name':'count','average_money':'mean'}).sort(columns='shop_name',ascending=False).head(10).plot(kind='bar',figsize=(20,10))
plt.title('shop_count')

-各菜系按评论数分类汇总,排名前五的为火锅、北京菜、日本菜、西餐、川菜。
In [76]:
ax=df_clean.groupby('cooking_style').agg({'comments1':'sum'}).sort(columns='comments1',ascending=False).head(10).plot(kind='bar',figsize=(20,10))
plt.title('comments1_sum')

3 热门商圈
-商圈数量按地区分类汇总,王府井/东单的餐厅数量最多;餐厅数量top 10 商圈的人均消费全部小于200元。
In [111]:
ax2=df_clean.groupby('region').agg({'region':'count','average_money':'mean'}).sort(columns='region',ascending=False).head(10).plot(kind='bar',figsize=(20,10))
plt.title('shop_count-region')

4 人均分布
-75%的餐厅人均小于130元。
In [87]:
df_clean.average_money.describe()
Out[87]:
count 731.000000
mean 123.980848
std 151.352821
min 4.000000
25% 67.000000
50% 90.000000
75% 130.000000
max 1842.000000
Name: average_money, dtype: float64
In [86]:
ax3=df_clean.average_money.plot(kind='hist',bins=20,figsize=(20,10))

-不同菜系人均消费
所有菜系中,私家菜人均消费最高;人均最高的餐厅为一家日本餐厅,人均>1750。
In [107]:
ax4=df_clean.boxplot(column='average_money',by='cooking_style',figsize=(20,15))
plt.title('average_money——cooking_style')
Out[107]:

-不同商圈人均消费
马桥/三里元商圈消费最高。
In [108]:
ax4=df_clean.boxplot(column='average_money',by='region',figsize=(20,10))
plt.title('average_money——region')
In [ ]:
