数据分析之Pandas
Posted Maverick_曲流觞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据分析之Pandas相关的知识,希望对你有一定的参考价值。
3.Pandas
文章目录
3.3 Pandas进阶
import pandas as pd
import numpy as np
3.3.1 数据重塑和轴向旋转
(1)层次化索引
层次化索引是pandas的一项重要功能,他能使我们再一个轴上拥有多个索引
Series的层次化索引
s=pd.Series(np.arange(1,10),index=[['a','a','a','b','b','c','c','d','d'],[1,2,3,1,2,3,1,2,3]])
s
a 1 1
2 2
3 3
b 1 4
2 5
c 3 6
1 7
d 2 8
3 9
dtype: int32
s.index
MultiIndex([('a', 1),
('a', 2),
('a', 3),
('b', 1),
('b', 2),
('c', 3),
('c', 1),
('d', 2),
('d', 3)],
)
s['a':'b']
a 1 1
2 2
3 3
b 1 4
2 5
dtype: int32
s[:,1]
a 1
b 4
c 7
dtype: int32
通过unstack方法可以将Series变成一个DataFrame
s.unstack()
1 | 2 | 3 | |
---|---|---|---|
a | 1.0 | 2.0 | 3.0 |
b | 4.0 | 5.0 | NaN |
c | 7.0 | NaN | 6.0 |
d | NaN | 8.0 | 9.0 |
s.unstack().stack()
a 1 1.0
2 2.0
3 3.0
b 1 4.0
2 5.0
c 1 7.0
3 6.0
d 2 8.0
3 9.0
dtype: float64
DataFrame的层次化索引
对于DataFrame来说,行和列都能够进行层次化索引。
data=pd.DataFrame(np.arange(12).reshape(4,3))
data
0 | 1 | 2 | |
---|---|---|---|
0 | 0 | 1 | 2 |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
3 | 9 | 10 | 11 |
data=pd.DataFrame(np.arange(12).reshape(4,3),index=[['a','a','b','b'],[1,2,1,2]])
data
0 | 1 | 2 | ||
---|---|---|---|---|
a | 1 | 0 | 1 | 2 |
2 | 3 | 4 | 5 | |
b | 1 | 6 | 7 | 8 |
2 | 9 | 10 | 11 |
data=pd.DataFrame(np.arange(12).reshape(4,3),index=[['a','a','b','b'],[1,2,1,2]],columns=[['A','A','B'],['Z','X','C']])
data
选取列
data['A']
设置名称
data.index.names=['row1','row2']
data
data.columns.names=['column1','column2']
data
行顺序调整
data.swaplevel('row1','row2')
层次化——电影数据示列
数据导入
df=pd.read_excel('movie_data2.xlsx')
df.head()
Unnamed: 0 | 名字 | 投票人数 | 类型 | 产地 | 上映时间 | 时长 | 年代 | 评分 | 首映地点 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 肖申克的救赎 | 692795 | 剧情/犯罪 | 美国 | 1994-09-10 00:00:00 | 142 | 1994 | 9.6 | 多伦多电影节 |
1 | 1 | 控方证人 | 42995 | 剧情/悬疑/犯罪 | 美国 | 1957-12-17 00:00:00 | 116 | 1957 | 9.5 | 美国 |
2 | 2 | 美丽人生 | 327855 | 剧情/喜剧/爱情 | 意大利 | 1997-12-20 00:00:00 | 116 | 1997 | 9.5 | 意大利 |
3 | 3 | 阿甘正传 | 580897 | 剧情/爱情 | 美国 | 1994-06-23 00:00:00 | 142 | 1994 | 9.4 | 洛杉矶首映 |
4 | 4 | 霸王别姬 | 478523 | 剧情/爱情/同性 | 中国大陆 | 1993-01-01 00:00:00 | 171 | 1993 | 9.4 | 香港 |
df.drop('Unnamed: 0',axis=1)
df.index
RangeIndex(start=0, stop=38166, step=1)
set_index:可以把列变成索引
reset_index:把索引变成列
把产地和年代同时设置成索引,产地是外层索引,年代是内层索引
df=df.set_index(['产地','年代'])
df.head()
每一个索引都是一个元组
df.index[0]
('美国', 1994)
获取所有的美国电影,由于产地信息已经变成了索引,因此可以用loc方法
df.loc['美国'].head()
| | 名字 | 投票人数 | 类型 | 上映时间 | 时长 | 评分 | 首映地点 |
| —: | —: | -----------: | -------: | -------------: | ------------------: | —: | —: | -----------: |
| 年代 | | | | | | | |
| 1994 | 肖申克的救赎 | 692795 | 剧情/犯罪 | 1994-09-10 00:00:00 | 142 | 9.6 | 多伦多电影节 |
| 1957 | 控方证人 | 42995 | 剧情/悬疑/犯罪 | 1957-12-17 00:00:00 | 116 | 9.5 | 美国 |
| 1994| 阿甘正传 | 580897 | 剧情/爱情 | 1994-06-23 00:00:00 | 142 | 9.4 | 洛杉矶首映 |
| 2012 | 泰坦尼克号 | 157074 | 剧情/爱情/灾难 | 2012-04-10 00:00:00 | 194 | 9.4 | 中国大陆 |
| 1993 | 辛德勒的名单 | 306904 | 剧情/历史/战争 | 1993-11-30 00:00:00 | 195 | 9.4 | 华盛顿首映 |
这样做最大的好处就是我们可以简化很多的筛选环节
索引交换 swaplevel
df=df.swaplevel('产地','年代')
df.head()
取消层次化索引
df=df.reset_index()
df.head()
年代 | 产地 | Unnamed: 0 | 名字 | 投票人数 | 类型 | 上映时间 | 时长 | 评分 | 首映地点 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1994 | 美国 | 0 | 肖申克的救赎 | 692795 | 剧情/犯罪 | 1994-09-10 00:00:00 | 142 | 9.6 | 多伦多电影节 |
1 | 1957 | 美国 | 1 | 控方证人 | 42995 | 剧情/悬疑/犯罪 | 1957-12-17 00:00:00 | 116 | 9.5 | 美国 |
2 | 1997 | 意大利 | 2 | 美丽人生 | 327855 | 剧情/喜剧/爱情 | 1997-12-20 00:00:00 | 116 | 9.5 | 意大利 |
3 | 1994 | 美国 | 3 | 阿甘正传 | 580897 | 剧情/爱情 | 1994-06-23 00:00:00 | 142 | 9.4 | 洛杉矶首映 |
4 | 1993 | 中国大陆 | 4 | 霸王别姬 | 478523 | 剧情/爱情/同性 | 1993-01-01 00:00:00 | 171 | 9.4 | 香港 |
(2)数据旋转
行列转化
data=df[:5]
data
年代 | 产地 | Unnamed: 0 | 名字 | 投票人数 | 类型 | 上映时间 | 时长 | 评分 | 首映地点 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1994 | 美国 | 0 | 肖申克的救赎 | 692795 | 剧情/犯罪 | 1994-09-10 00:00:00 | 142 | 9.6 | 多伦多电影节 |
1 | 1957 | 美国 | 1 | 控方证人 | 42995 | 剧情/悬疑/犯罪 | 1957-12-17 00:00:00 | 116 | 9.5 | 美国 |
2 | 1997 | 意大利 | 2 | 美丽人生 | 327855 | 剧情/喜剧/爱情 | 1997-12-20 00:00:00 | 116 | 9.5 | 意大利 |
3 | 1994 | 美国 | 3 | 阿甘正传 | 580897 | 剧情/爱情 | 1994-06-23 00:00:00 | 142 | 9.4 | 洛杉矶首映 |
4 | 1993 | 中国大陆 | 4 | 霸王别姬 | 478523 | 剧情/爱情/同性 | 1993-01-01 00:00:00 | 171 | 9.4 | 香港 |
T 可以直接让数据的行和列进行交换
data.T
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
年代 | 1994 | 1957 | 1997 | 1994 | 1993 |
产地 | 美国 | 美国 | 意大利 | 美国 | 中国大陆 |
Unnamed: 0 | 0 | 1 | 2 | 3 | 4 |
名字 | 肖申克的救赎 | 控方证人 | 美丽人生 | 阿甘正传 | 霸王别姬 |
投票人数 | 692795 | 42995 | 327855 | 580897 | 478523 |
类型 | 剧情/犯罪 | 剧情/悬疑/犯罪 | 剧情/喜剧/爱情 | 剧情/爱情 | 剧情/爱情/同性 |
上映时间 | 1994-09-10 00:00:00 | 1957-12-17 00:00:00 | 1997-12-20 00:00:00 | 1994-06-23 00:00:00 | 1993-01-01 00:00:00 |
时长 | 142 | 116 | 116 | 142 | 171 |
评分 | 9.6 | 9.5 | 9.5 | 9.4 | 9.4 |
首映地点 | 多伦多电影节 | 美国 | 意大利 | 洛杉矶首映 | 香港 |
dataframe也可以使用stack和unstack,转化为层次索引的Series
data.stack()
0 年代 1994
产地 美国
Unnamed: 0 0
名字 肖申克的救赎
投票人数 692795
类型 剧情/犯罪
上映时间 1994-09-10 00:00:00
时长 142
评分 9.6
首映地点 多伦多电影节
1 年代 1957
产地 美国
Unnamed: 0 1
名字 控方证人
投票人数 42995
类型 剧情/悬疑/犯罪
上映时间 1957-12-17 00:00:00
时长 116
评分 9.5
首映地点 美国
2 年代 1997
产地 意大利
Unnamed: 0 2
名字 美丽人生
投票人数 327855
类型 剧情/喜剧/爱情
上映时间 1997-12-20 00:00:00
时长 116
评分 9.5
首映地点 意大利
3 年代 1994
产地 美国
Unnamed: 0 3
名字 阿甘正传
投票人数 580897
类型 剧情/爱情
上映时间 1994-06-23 00:00:00
时长 142
评分 9.4
首映地点 洛杉矶首映
4 年代 1993
产地 中国大陆
Unnamed: 0 4
名字 霸王别姬
投票人数 478523
类型 剧情/爱情/同性
上映时间 1993-01-01 00:00:00
时长 171
评分 9.4
首映地点 香港
dtype: object
data.stack().unstack()
年代 | 产地 | Unnamed: 0 | 名字 | 投票人数 | 类型 | 上映时间 | 时长 | 评分 | 首映地点 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1994 | 美国 | 0 | 肖申克的救赎 | 692795 | 剧情/犯罪 | 1994-09-10 | 142 | 9.6 | 多伦多电影节 |
1 | 1957 | 美国 | 1 | 控方证人 | 42995 | 剧情/悬疑/犯罪 | 1957-12-17 | 116 | 9.5 | 美国 |
2 | 1997 | 意大利 | 2 | 美丽人生 | 327855 | 剧情/喜剧/爱情 | 1997-12-20 | 116 | 9.5 | 意大利 |
3 | 1994 | 美国 | 3 | 阿甘正传 | 580897 | 剧情/爱情 | 1994-06-23 | 142 | 9.4 | 洛杉矶首映 |
4 | 1993 | 中国大陆 | 4 | 霸王别姬 | 478523 | 剧情/爱情/同性 | 1993-01-01 | 171 | 9.4 | 香港 |
3.3.2 数据分组、分组运算
GroupBy技术:实现数据的分组,和分组运算,作用类似于数据透视表
按照电影产地进行分组
先定义一个分组变量group
group=df.groupby(df['产地'])
group
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002238D9028B0>
可以计算分组后的各个统计量
group.mean().head()
年代 | Unnamed: 0 | 投票人数 | 时长 | 评分 | |
---|---|---|---|---|---|
产地 | |||||
中国台湾 | 1999.009709 | 19350.590615 | 8474.864078 | 87.257282 | 7.066667 |
中国大陆 | 2004.599684 | 20391.791426 | 10898.293793 | 81.432930 | 6.064703 |
中国香港 | 1991.100316 | 19230.117152 | 8167.446159 | 88.541214 | 6.474114 |
丹麦 | 1999.090909 | 20415.611111 | 1993.858586 | 88.101010 | 7.245960 |
俄罗斯 | 1992.534129 | 20061.753479 | 2098.813784 | 93.280981 | 7.310736 |
计算每年的平均评分
df['评分'].groupby(df['年代']).mean().head()
年代
1888 7.950000
1890 4.800000
1892 7.500000
1894 6.633333
1895 7.575000
Name: 评分, dtype: float64
只会对数值变量进行分组运算
df['年代']=df['年代'].astype('str')
df.groupby(df['产地']).mean().head()
Unnamed: 0 | 投票人数 | 时长 | 评分 | |
---|---|---|---|---|
产地 | ||||
中国台湾 | 19350.590615 | 8474.864078 | 87.257282 | 7.066667 |
中国大陆 | 20391.791426 | 10898.293793 | 81.432930 | 6.064703 |
中国香港 | 19230.117152 | 8167.446159 | 88.541214 | 6.474114 |
丹麦 | 20415.611111 | 1993.858586 | 88.101010 | 7.245960 |
俄罗斯 | 20061.753479 | 2098.813784 | 93.280981 | 7.310736 |
我们也可以传入多个分组变量
df.groupby([df['产地'],df['年代']]).mean().head()
Unnamed: 0 | 投票人数 | 时长 | 评分 | ||
---|---|---|---|---|---|
产地 | 年代 | ||||
中国台湾 | 1963 | 14805.0 | 121.000000 | 113.0 | 6.4 |
1965 | 30282.0 | 153.666667 | 105.0 | 6.8 | |
1966 | 26305.0 | 51.000000 | 60.0 | 7.9 | |
1967 | 16605.0 | 4444.000000 | 112.0 | 8.0 | |
1968 | 21282.5 | 89.000000 | 83.0 | 7.4 |
获得每个地区,每一年的电影的评分的均值
df['评分'].groupby([df['产地'],df['年代']]).mean()
产地 年代
中国台湾 1963 6.400000
1965 6.800000
1966 7.900000
1967 8.000000
1968 7.400000
...
韩国 2012 6.064151
2013 6.098198
2014 5.650833
2015 5.423853
2016 5.730000
Name: 评分, Length: 1511, dtype: float64
Series通过unstack方法转化为dataframe——会产生缺失值
df['评分'].groupby([df['产地'],df['年代']]).mean().unstack().head()
年代 | 1888 | 1890 | 1892 | 1894 | 1895 | 1896 | 1897 | 1898 | 1899 | 1900 | … | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
产地 | |||||||||||||||||||||
中国台湾 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | … | 7.420000 | 7.100000 | 7.053846 | 7.231818 | 6.556098 | 7.076471 | 6.522222 | 6.576000 | NaN | NaN |
中国大陆 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | … | 6.589726 | 6.536628 | 6.357831 | 5.824606 | 5.727187 | 5.316667 | 4.963757 | 4.969189 | 4.712000 | NaN |
中国香港 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | … | 6.476786 | 6.442553 | 6.245455 | 5.971053 | 6.110526 | 6.105714 | 5.616667 | 5.589189 | 5.390909 | NaN |
丹麦 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | … | 7.050000 | 7.118182 | 7.362500 | 7.016667 | 7.418750 | 6.555556 | 7.120000 | 7.166667 | 7.000000 | NaN |
俄罗斯 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | … | 7.024468 | 6.922727 | 6.974324 | 7.006000 | 6.784127 | 6.890566 | 6.965957 | 7.089655 | NaN | NaN |
5 rows × 127 columns
3.3.3 离散化处理
再实际的数据分析项目中,对有的数据属性,我们往往并不关注数据的绝对取值,只关注它所处的区间或等级。
比如我们可以把评分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=True:默认包括右端点
include_lowest=False:默认不包括左端点
labels:是否要用标记替换分组
retbins:返回x中对应的bins的列表
precision:精度
df['评分等级']=pd.cut(df['评分'],[0,3,5,7,9,10],labels=['E','D','C','B','A'])
df
年代 | 产地 | Unnamed: 0 | 名字 | 投票人数 | 类型 | 上映时间 | 时长 | 评分 | 首映地点 | 评分等级 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1994 | 美国 | 0 | 肖申克的救赎 | 692795 | 剧情/犯罪 | 1994-09-10 00:00:00 | 142 | 9.600000 | 多伦多电影节 | A |
1 | 1957 | 美国 | 1 | 控方证人 | 42995 | 剧情/悬疑/犯罪 | 1957-12-17 00:00:00 | 116 | 9.500000 | 美国 | A |
2 | 1997 | 意大利 | 2 | 美丽人生 | 327855 | 剧情/喜剧/爱情 | 1997-12-20 00:00:00 | 116 | 9.500000 | 意大利 | A |
3 | 1994 | 美国 | 3 | 阿甘正传 | 580897 | 剧情/爱情 | 1994-06-23 00:00:00 | 142 | 9.400000 | 洛杉矶首映 | A |
4 | 1993 | 中国大陆 | 4 | 霸王别姬 | 478523 | 剧情/爱情/同性 | 1993-01-01 00:00:00 | 171 | 9.400000 | 香港 | A |
… | … | … | … | … | … | … | … | … | … | … | … |
38725 | 1935 | 美国 | 38728 | 1935年 | 57 | 喜剧/歌舞 | 1935-03-15 00:00:00 | 98 | 7.600000 | 美国 | B |
38726 | 1986 | 中国大陆 | 38729 | 血溅画屏 | 95 | 剧情/悬疑/犯罪/武侠/古装 | 1905-06-08 00:00:00 | 91 | 7.100000 | 美国 | B |
38727 | 1986 | 中国大陆 | 38730 | 魔窟中的幻想 | 51 | 惊悚/恐怖/儿童 | 1905-06-08 00:00:00 | 78 | 8.000000 | 美国 | B |
38728 | 1977 | 俄罗斯 | 38731 | 列宁格勒围困之星火战役 Блокада: Фильм 2: Ленинградский ме… | 32 | 剧情/战争 | 1905-05-30 00:00:00 | 97 | 6.600000 | 美国 | C |
38729 | 2017 | 美国 | 38732 | 复仇者联盟3 | 123456 | 剧情/科幻 | 2017-05-04 00:00:00 | 142 | 6.935704 | 美国 | C |
38730 rows × 11 columns
根据投票人数来刻画电影的热门
投票人数越多,热门程度越高
使用 np.percentile 进行分位数计算
bins=np.percentile(df['投票人数'],[0,20,40,60,80,100])
df['热门程度']=pd.cut(df['投票人数'],bins,labels=['E','D','C','B','A'])
df
年代 | 产地 | Unnamed: 0 | 名字 | 投票人数 | 类型 | 上映时间 | 时长 | 评分 | 首映地点 | 评分等级 | 热门程度 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1994 | 美国 | 0 | 肖申克的救赎 | 692795 | 剧情/犯罪 | 1994-09-10 00:00:00 | 142 | 9.600000 | 多伦多电影节 | A | A |
1 | 1957 | 美国 | 1 | 控方证人 | 42995 | 剧情/悬疑/犯罪 | 1957-12-17 00:00:00 | 116 | 9.500000 | 美国 | A | A |
2 | 1997 | 意大利 | 2 | 美丽人生 | 327855 | 剧情/喜剧/爱情 | 1997-12-20 00:00:00 | 116 | 9.500000 | 意大利 | A | A |
3 | 1994 | 美国 | 3 | 阿甘正传 | 580897 | 剧情/爱情 | 1994-06-23 00:00:00 | 142 | 9.400000 | 洛杉矶首映 | A | A |
4 | 1993 | 中国大陆 | 4 | 霸王别姬 | 478523 | 剧情/爱情/同性 | 1993-01-01 00:00:00 | 171 | 9.400000 | 香港 | A | A |
… | … | … | … | … | … | … | … | … | … | … | … | … |
38725 | 1935 | 美国 | 38728 | 1935年 | 57 | 喜剧/歌舞 | 1935-03-15 00:00:00 | 98 | 7.600000 | 美国 | B | E |
38726 | 1986 | 中国大陆 | 38729 | 血溅画屏 | 95 | 剧情/悬疑/犯罪/武侠/古装 | 1905-06-08 00:00:00 | 91 | 7.100000 | 美国 | B | D |
38727 | 1986 | 中国大陆 | 38730 | 魔窟中的幻想 | 51 | 惊悚/恐怖/儿童 | 1905-06-08 00:00:00 | 78 | 8.000000 | 美国 | B | E |
38728 | 1977 | 俄罗斯 | 38731 | 列宁格勒围困之星火战役 Блокада: Фильм 2: Ленинградский ме… | 32 | 剧情/战争 | 1905-05-30 00:00:00 | 97 | 6.600000 | 美国 | C | E |
38729 | 2017 | 美国 | 38732 | 复仇者联盟3 | 123456 | 剧情/科幻 | 2017-05-04 00:00:00 | 142 | 6.935704 | 美国 | C | A |
38730 rows × 12 columns
查看烂片:投票人数多,评分低
df[(df.热门程度=='A')&(df.评分等级=='E')]
年代 | 产地 | Unnamed: 0 | 名字 | 投票人数 | 类型 | 上映时间 | 时长 | 评分 | 首映地点 | 评分等级 | 热门程度 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
655 | 2011 | 中国大陆 | 655 | B区 | 5187 | 剧情/惊悚/恐怖 | 2011-06-03 00:00:00 | 89 | 2.3 | 中国大陆 | E | A |
4376 | 2014 | 中国大陆 | 4376 | 怖偶 | 4867 | 悬疑/惊悚 | 2014-05-07 00:00:00 | 88 | 2.8 | 中国大陆 | E | A |
5413 | 2011 | 中国大陆 | 5413 | 床下有人 | 4309 | 悬疑/惊悚 | 2011-10-14 00:00:00 | 100 | 2.8 | 中国大陆 | E | A |
6802 | 2013 | 中国大陆 | 6802 | 帝国秘符 | 4351 | 动作/冒险 | 2013-09-18 00:00:00 | 93 | 3.0 | 中国大陆 | E | A |
8232 | 2011 | 中国大陆 | 8232 | 飞天 | 4764 | 剧情 | 2011-07-01 00:00:00 | 115 | 2.9 | 中国大陆 | E | A |
8406 | 2014 | 中国大陆 |