pandas实战——对星巴克数据的分析
一、实验对象
实验对象为星巴克在全球的门店数据,我们可以使用pandas对其进行简单的分析,如分析每个国家星巴克的数量,根据门店数量对国家进行排序等。
二、数据分析
1、读取数据并获取数据行列数
首先读取数据:
import numpy as np
import pandas as pd
starbucks = pd.read_csv("D:\\directory.csv")
print "数据的列标签如下:"
print starbucks.columns
print "每列的数据类型:"
print starbucks.dtypes
print "文件行数:"
print len(starbucks.index)
print "文件列数:"
print starbucks.columns.size
输出:
数据的列标签如下:
Index([u'Brand', u'Store Number', u'Store Name', u'Ownership Type',
u'Street Address', u'City', u'State/Province', u'Country', u'Postcode',
u'Phone Number', u'Timezone', u'Longitude', u'Latitude'],
dtype='object')
每列的数据类型:
Brand object
Store Number object
Store Name object
Ownership Type object
Street Address object
City object
State/Province object
Country object
Postcode object
Phone Number object
Timezone object
Longitude float64
Latitude float64
dtype: object
文件行数:
25600
文件列数:
13
可以看到文件共有25600条数据,每条数据有13列。
2、查看数据
#查看文件的前五行数据
print starbucks.head()
输出:
可以通过DataFrame.head(n)来获取数据帧的前n行数据,未指定n则返回前5行,同样的函数还有DataFrame.tail(n)。上图中有些数据为NaN,如果NaN对数据处理有影响的话可以使用DataFrame.fillna(value)将NaN替换成value,或者使用DataFrame.dropna()删除含有NaN的行。本文将不对NaN做处理。
3、按照星巴克数量由多到少对国家排序
要实现这个功能需要用到DataFrame.groupby()函数,相当于sql中的group by
。在本例中可以使用starbucks.groupby(["Country"])来对星巴克按国家分组,然后使用starbucks.groupby(["Country"]).size()求得每个国家有多少星巴克。
df = starbucks.groupby(["Country"]).size().reset_index()
输出:
Country
AD 1
AE 144
AR 108
AT 18
AU 22
AW 3
AZ 4
BE 19
BG 5
BH 21
BN 5
BO 4
BR 102
BS 10
CA 1468
CH 61
CL 96
CN 2734
CO 11
CR 11
CW 3
CY 10
CZ 28
DE 160
DK 21
EG 31
ES 101
FI 8
FR 132
GB 901
...
LU 2
MA 9
MC 2
MX 579
MY 234
NL 59
NO 17
NZ 24
OM 12
PA 5
PE 89
PH 298
PL 53
PR 24
PT 11
QA 18
RO 27
RU 109
SA 102
SE 18
SG 130
SK 3
SV 11
TH 289
TR 326
TT 3
TW 394
US 13608
VN 25
ZA 3
Length: 73, dtype: int64
然后我们将上一步的结果使用reset_index()方法封装成一个新的DataFrame,然后对这个DataFrame排序即可。
#根据每个国家的国家名和星巴克数量重建为一个DataFrame
df = starbucks.groupby(["Country"]).size().reset_index()
#查看df的前5行数据
print df.head()
#修改列名(将“0”改为“Nums”)
df.columns=["Country", "Nums"]
#按照星巴克数量由多到少对国家排序
df.sort_values(by=["Nums"], ascending=False).head()
输出:
Country 0
0 AD 1
1 AE 144
2 AR 108
3 AT 18
4 AU 22
Country Nums
70 US 13608
17 CN 2734
14 CA 1468
37 JP 1237
39 KR 993
可以看到,美国的星巴克最多,有13608家,其次是中国、加拿大、日本、韩国。由于篇幅限制只显示了排序后的5行,可以去掉head()显示全部数据。
4、按星巴克数量多少对中国城市排序
首先要在所有国家的数据中选择中国的数据,可以使用布尔索引实现这一目的:
#选择中国的数据
df = starbucks[starbucks["Country"]=="CN"]
#统计每个城市的星巴克数量
df.groupby(["City"]).size()
输出:
City
Admiralty 2
Causeway Bay 5
Central 1
Chaiwan 1
Changshu 1
Changzhou 1
Fortress Hill 1
Hangzhou 2
Hong Kong 104
Jiaxing 2
Jinhua 1
Kowloon 19
Kowloon Bay 1
Kowloon Tong 1
Lantau Island 2
Macau 13
Mong Kok 2
N.T. 2
Nanjing 1
Nantong 4
New Territories 7
Ningbo 3
Quarry Bay 3
ShangHai 2
Shanghai 2
Shantin 1
Stanley 1
Suzhou 3
Tai Koo Shing 1
Tin Hau 1
...
萧山市 1
蚌埠市 1
衡阳市 3
衢州市 3
襄樊市 1
襄阳市 2
西宁市 3
西安市 40
诸暨市 2
贵阳 8
贵阳市 1
连云港 1
连云港市 3
邢台市 1
邯郸 1
郑州市 18
重庆市 41
金华市 11
银川市 2
镇江市 9
长春市 10
长沙市 26
阳江市 1
青岛市 28
靖江市 2
鞍山市 3
马鞍山 3
高邮市 1
黄石市 1
龙岩市 2
Length: 197, dtype: int64
可以看到数据不是很规范,城市名称既有中文又有英文,而且上海被存储为ShangHai
和Shanghai
。对于上海的问题,我们将拼音全部改为小写即可;对于中文和拼音混用的问题,可以使用相应的python库(如库pinyin
)将中文转换为拼音后作统计。
首先安装库pinyin,如果是在命令行里运行的python,直接pip install pinyin
,安装成功后import pinyin
即可。我是在jupyter notebook里面写的,外部pip安装的模块无法导入,所以使用下面的方法(或者使用conda
命令安装):
import pip
pip.main(['install', 'pinyin'])
安装后导入并做相应的处理:
import pinyin
#选择中国的数据
df = starbucks[starbucks["Country"]=="CN"]
#需要拷贝一下,不然会出现“A value is trying to be set on a copy of a slice from a DataFrame.”的警告
df1 = df.copy()
#将城市名改为小写
df1["City"] = df1["City"].apply(lambda x:x.lower())
df2 = df1.copy()
#将汉字城市名改为小写拼音
df2["City"] = df2["City"].apply(lambda x:pinyin.get(x, format="strip", delimiter="")[0:-3]) #去掉“市”的拼音
#统计每个城市的星巴克数量
df2.groupby(["City"]).size()
输出:
City
admira 2
anshan 3
bangbu 1
baoding 3
baoji 1
baotou 4
beihai 1
beijing 234
causeway 5
cent 1
chai 1
chang 1
changchun 10
changsha 26
changshu 6
changz 1
changzhou 26
chengde 1
chengdu 98
cixi 5
dali 1
dalian 25
danzhou 1
daqing 2
deyang 2
dezhou 2
dongguan 31
dongyang 1
dongying 1
fenghua 2
...
yancheng 6
yangjiang 1
yangzhong 1
yangzhou 12
yanji 1
yantai 8
yichang 4
yinchuan 2
yingkou 2
yiwu 2
yixing 3
yuen l 2
yueyang 2
yuyao 1
zhangjia 1
zhangjiag 1
zhangjiagang 1
zhangzhou 1
zhanjiang 4
zhaoqing 1
zhengzhou 18
zhenjiang 9
zhongqing 41
zhongshan 11
zhous 1
zhoushan 5
zhuhai 14
zhuji 2
zhuzhou 2
zibo 5
Length: 192, dtype: int64
这里使用到了DataFrame.apply(func)方法,该方法将函数func应用到整个DataFrame上,也可以通过指定axis参数来指定每一行或每一列的数据应用函数func。
接下来使用reset_index方法将上一步得到的数据封装到一个新的DataFrame中排序即可。
df3 = df2.groupby(["City"]).size().reset_index()
#更改列索引名称
df3.columns = ["City", "Nums"]
print df3.sort_values(by=["Nums"], ascending=False).head()
输出:
City Nums
121 shanghai 542
7 beijing 234
46 hangzhou 117
126 shenzhen 113
36 guangzhou 106
可以看到在中国,上海的星巴克最多,有542家,其次的是北京、杭州、深圳和广州,去掉.head()
可以查看所有城市的数据。
三、总结
本文主要按照星巴克数量对国家和中国的城市进行排序,用到的知识有:
- 使用DataFrame.groupby()方法对DataFrame按照一列或多列分组;
- 使用布尔索引选择数据;
- 使用DataFrame.reset_index()方法重新指定索引(也就是把原DataFrame的行索引也当做数据并重新指定索引),该方法返回一个新的DataFrame;
- 通过对DataFrame.columns的赋值,重新指定列标签;
- 使用DataFrame.apply(func)方法,将函数func应用到整个DataFrame上,也可以通过指定axis参数来指定每一行或每一列的数据应用函数func。
- 使用DataFrame.sort()方法对DataFrame按照某一列或者某几列进行排序。
我们也可以看到一些pandas的操作可以与SQL操作练习起来:
1、Where语句
在上文中我们使用布尔索引选择了中国的数据df = starbucks[starbucks["Country"]=="CN"]
,这一点很像SQL里面的where语句select * from starbucks where Country="CN"
。
2、Select语句
starbucks有很多列,如Country,City,Brand,Postcode等,如果我们要从所有列中选择两列Country和City,则pandas可以使用df = starbucks[["Country", "City"]]
,与之对应的是SQL中的select语句select Country, City from starbucks
;
3、Group by语句
上文中通过国家分组,pandas使用DataFrame.groupby()方法starbucks.groupby(["Country"])
,对应的为SQL中的select * from starbucks group by Country
。