一 緒論¶
分析背景:美食薈萃的北京東城區,哪家餐廳最熱門,哪家餐廳口味好,哪種菜系最受歡迎,哪個區域餐廳最多,人均消費與區域、菜系的關係?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 [ ]: