@[toc]
前提准备
先导包
import numpy as np
import pandas as pd
再读数据
df = pd.read_excel(r'D:\数据分析\movie_data2.xlsx')
这样才能正式开始学习
数据重塑(层次化索引)和轴向旋转(数据旋转)
层次化索引
一个轴上拥有多个索引,使⾼维数据可以被紧凑的表示在我们熟悉的⼀维Series和⼆维DataFrame对象中,即降低维度形式处理高维度数据。
Series的层次化索引
多重索引通过 index
参数实现:
s = pd.Series(np.arange(1,10),index = [['a','a','a','b','b','c','c','d','d'],[1,2,3,1,2,1,2,1,2]])
查看索引:
s.index
MultiIndex 意思是:多索引
切片:
s.b
# 或
s['b']
s['a':'c']
取内层:
逗号(,)前是外层,逗号(,)后是内层
取所有外层的 索引为1内层:
s[:,1]
取(c,2)元素:
s['c',2]
通过 unstack
(不堆叠)方法可以将Series变成一个DataFrame
s.unstack()
外层为行,内层为列
DataFrame的层次化索引
对于DataFrame,行和列都能够进行层次化索引。
先构造一个默认索引的DataFrame:
data = pd.DataFrame(np.arange(1,13).reshape(4,3)) # np.arange生成数据,reshape重构结构
默认索引都从0开始
对 行 进行层次化索引
data = pd.DataFrame(np.arange(1,13).reshape(4,3),index = [['a','a','b','b'],[1,2,1,2]])
对 列 也进行层次化索引
data = pd.DataFrame(np.arange(1,13).reshape(4,3),index = [['a','a','b','b'],[1,2,1,2]],columns = [['A','A','B'],['X','Y','Z']])
选取列:
参数只能是A或B
data['A']
设置行或列的名称:
- index.names
- columns.names
data.index.names = ['row1','row2']
data.columns.names = ['col1','col2']
调整 索引 顺序:
- swaplevel :交换内、外层索引
调整row1,row2的顺序
data.swaplevel('row1','row2')
列与索引之间的转换
set_index
可以把列变成索引reset_index
是把索引变成列
了解了层次化索引的基本知识以后,将电影数据也处理成一种多层索引的结构。
df.index
这是原始的单层索引
把产地和年代同时设成索引,产地是外层索引,年代为内层索引
用 set_index
:
df = df.set_index(['产地','年代']) # 外层写前面,内层写后面
顺序很重要!外层写前面,内层写后面。
每个索引都是一个元组
df.index[4]
获取所有的美国电影。由于产地信息已经变成了索引,因此要用 .loc 方法
df.loc['美国',:]
# 或省略后面参数
df.loc['美国']
loc 的使用在:通过标签选择数据 —— loc
取消层次化索引,把索引变回列
用 reset_index
:
df = df.reset_index(['产地','年代'])
# 或
# 如果是全部取消,就可以省略参数
df = df.reset_index()
数据旋转
拿前5部电影为例
data = df.head()
.T
可以直接让数据的行列进行交换
data.T
DataFrame可以使用stack
,转化为层次化索引的Series
data = data.stack()
此时数据为层次化的 Series
层次化索引的Series可以使用unstack
,转化为DataFrame
data = data.unstack()
没有数据时,会产生缺失值 NaN。
数据分组和分组运算
groupby
:能实现数据的分组和分组运算,作用类似于数据透视表
把相同键进行分组,再把每组的值进行运算。
先定义一个分组变量 group,按照电影的产地进行分组
group = df.groupby(df['产地'])
此时group是DataFrame下GroupBy的对象
计算分组后的各个统计量
# 均值
group.mean()
# 求和
group.sum()
计算每年的平均评分
df['评分'].groupby(df['年代']).mean()
只会对数值变量进行分组计算
求平均时不想带上年代,就把年代转为字符串类型就行
df.年代 = df.年代.astype('str')
这时再分组,就不会对年代求平均了
df.groupby(df.产地).mean()
传入多个分组变量
df.groupby([df.产地,df.年代]).mean()
获得每个地区,每一年的电影的评分的均值
df.groupby([df.产地,df.年代])['评分'].mean()
# 或
df['评分'].groupby([df.产地,df.年代]).mean()
数据离散化
在实际的数据分析项目中,对有的数据属性,我们往往并不关注数据的绝对取值,只关注它所处的区间或者等级。即,我们往往取得是一个区间的数据,而非简单一个值的数据。
比如,我们可以把评分9分及以上的电影定义为A,7到9分定义为B,5到7分定义为C,3到5分定义为D,小于3分定义为E。
离散化也可称为分组、区间化
Pandas提供了方便的函数 cut()
:
pd.cut(x, bins, right = True, labels = None, retbins = False, precision = 3, include_lowest = False)
参数:
x
:需要离散化的数组,Series、DataFrame对象bins
:分组的依据right
:是否包含右端点,默认为Trueinclude_lowest
:是否包含左端点,默认为Falselabels
:是否用标记替换返回出来的分组bins
后面这俩不常用👇
- retbins :返回x中每个值对应的bins列表
- precision :精度
评分9分及以上的电影定义为A,7到9分定义为B,5到7分定义为C,3到5分定义为D,小于3分定义为E
如果不定义labels:
pd.cut(df['评分'],[0,3,5,7,9,10])
每个区间都是默认的左开右闭
定义labels:
pd.cut(df['评分'],[0,3,5,7,9,10],labels = ['E','D','C','B','A'])
把评分等级这列加在数据集中:
df['评分等级'] = pd.cut(df['评分'],[0,3,5,7,9,10],labels = ['E','D','C','B','A'])
根据投票人数划分电影的热门程度。投票人数越多,热门程度越高
1.先弄出来bins,有个分组依据。否则哪什么划分程度呀
bins = np.percentile(df['投票人数'],[0,20,40,60,80,100])
np.percentile
参数:
a
:数组array,用来算分位数的对象,可以是多维的数组q
:介于0-100的 float 数,用来计算是几分位的参数
2.写 cut
df['热门程度'] = pd.cut(df['投票人数'],bins,labels = ['差劲','不太行','一般般','比较热','大热门'])
大烂片合集:投票人数很多,评分很低
df[(df.热门程度 == '大热门') & (df.评分等级 == 'E')]
妈耶!几乎全是中国电影
冷门高分电影
df[(df.热门程度 == '差劲') & (df.评分等级 == 'A')]
将处理后的数据进行保存
df.to_excel(r'D:\数据分析\movie_data3.xlsx')
合并数据集
(1)append
把产地为中国和产地为美国的电影数据从数据集中拆分出来,再合并
先把数据集拆分为多个
df_usa = df[df.产地 == '美国']
df_china = df[df.产地 == '中国大陆']
将这两个数据集进行合并
df_china.append(df_usa)
(2)merge ⭐
merge 用来合并Series或DataFrame。
只能用于两个表的拼接,且连接方向是左右拼接,一个左表一个右表。
pd.merge(left, right, how = 'inner', on = None, left_on = None, right_on = None, left_index = False, right_index = False, sort = True, suffixes = ('_x', '_y'), copy = True, indicator = False)
参数:
left
:对象 —— 左边待拼接的数据文件right
:另一个对象 —— 右边待拼接的数据文件how
:通过什么方式连接数据。有 left 返回的结果只包含左列、right 返回的结果只包含右列、outer 并集、inner 交集几个值,默认为inner。on
:以什么字段进行拼接(哪个字段作为主键(连接键)),该字段必须在左右数据中都存在。如果两个表里没有完全一致的列名,但是有信息一致的列,就需要用 left_on 和 right_on 共同来指定。left_on
:左表的连接键字段right_on
:右表的连接键字段left_index
:如果为True,则将左表的索引作为连接键。默认为Falseright_index
:如果为True,则将右表的索引作为连接键。默认为Falsesort
:通过连接键,按字典顺序对结果进行排序。suffixes
:如果左右数据出现重复列,新数据表头会用此后缀进行区分,默认为 _x 和 _ycopy
:始终从传递的DataFrame对象复制数据(默认为True),即使不需要重建索引也是如此。indicator
:显示拼接后的表中数据来自于哪一个表格。表的最后会有一个新列 _merge,显示这一条记录来自于左右哪个表,left_only或right_only。如果两表都有数据会标记both,默认为False。
练习:
选取6部热门电影:
df1 = df.loc[:5]
df2 = df.loc[:5][['名字','产地']]
df2['票房'] = [16543,6498,68786,4897664,79784,35767]
打乱 df2 数据:
df2 = df2.sample(frac = 1)
重新给 df2 赋索引 :
df2.index = range(len(df2))
上面这一通操作,只打乱了数据,而没打乱索引。
把 df1 和 df2 合并:
我们发现,df2有票房数据,df1有评分等其他信息。
由于样本的index索引顺序不一致,因此不能采用直接复制的方法。
根据电影名字合并(电影名字作主键)
pd.merge(df1,df2,how = 'inner',on = '名字')
因为 df1 和 df2 中都有产地,所以列名后面自动加了 _x 和 _y
(3)concat
将多个数据集进行批量合并
先弄三个数据集:
df1 = df[:10]
df2 = df[100:110]
df3 = df[200:210]
再合并:
dff = pd.concat([df1,df2,df3])
作业
(1)读取数据。读取之前作业保存的 “酒店数据1.xlsx”
df = pd.read_excel(r'D:\数据分析\酒店数据.xlsx')
(2)将“类型”和“名字”设置为层次化索引,并交换索引的位置。然后将层次化索引取消。
# 层次化索引
df = df.set_index(['类型','名字'])
# 交换索引位置
df.swaplevel('类型','名字')
# 取消层次化索引
df = df.reset_index()
(3)将数据集转置,获取转置后的index和columns。
# 转置
data = df.T
data.index
data.columns
(4)用groupby方法计算每个地区的评分人数的总和以及均值
group = df['评分人数'].groupby(df['地区'])
group.sum()
group.mean()
(5)用groupby方法计算每个类型的平均价格,,最高价和最低价
group = df['价格'].groupby(df['类型']).mean()
group.max()
group.min()
(6)数据离散化,按照价格将酒店分为3个等级,0-500为C,500-1000为B,大于1000为A,列名设置为“价格等级”
df['价格等级'] = pd.cut(df['价格'],[0,500,1000,1000000],labels = ['C','B','A'])
(7)获取评分均值最高和最低的地区的数据,分别使用append和concat方法将获取的两个数据集合并
group = df['评分'].groupby(df['地区']).mean()
group.sort_values()
默认升序排列,最下面的“屯门”评分均值最高,最上面的“葵青”评分均值最低。
df1 = df[df.地区 == '屯门']
df2 = df[df.地区 == '葵青']
df1.append(df2)
pd.concat([df1,df2])
(8)数据离散化,按照评分人数将酒店平均分为3个等级,三个等级的酒店数量尽量保持一致。评分人数最多的为A,最少的为C。列名设置为“热门等级”
bins = np.percentile(df['评分人数'],[0,33,66,100])
df['热门等级'] = pd.cut(df['评分人数'],bins,labels = ['C','B','A'])
(9)选出热门等级为A,价格等级也为A的酒店数据,计算其平均评分
temp1 = df.loc[(df.热门等级 == 'A') & (df.价格等级 == 'A')]
temp1['评分'].mean()
(10)取价格最高的5个酒店数据,使用stack和unstack方法实现DataFrame和Series之间的转换
data = df.sort_values('价格',ascending = False)[:5]
data = data.stack()
data = data.unstack()
(11)纵向拆分数据集,分为df1和df2,df1包含类型,名字,城市,地区;df2包含名字,地点,评分,评分人数,价格,价格等级,热门等级
df1 = df.loc[:][['类型','名字','城市','地区']]
df2 = df.loc[:][['名字','地点','评分','评分人数','价格','价格等级','热门等级']]
(12)将df2按照价格进行排序,重新设置df2的索引。索引值等于价格排名(从1开始依次加一)。
df2 = df2.sort_values('价格')
此时索引index很乱,需重新设置
df2.index = range(len(df2))
(13)使用merge方法将df1和df2合并。
df = pd.merge(df1,df2,on = '名字')
(14)将合并后的数据集保存数据到“酒店数据2.xlsx”。
df.to_excel(r'D:\数据分析\酒店数据2.xlsx')