第一篇
1.1 pandas 基本介绍
pandas是基于Numpy的一种工具,该工具是为了解决数据分析任务而创建的。Pandas纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具,同时也提供大量能使我们快速便捷的处理数据的函数和方法。
在pandas中有两类非常重要的数据结构,即序列Series和数据框DataFrame。Series类似于numpy中的一维数组,除了通吃一维数组可用的函数或方法,而且其可通过索引标签的方式获取数据,还具有索引的自动对齐功能;DataFrame类似于numpy中的二维数组,同样可以通用numpy数组的函数和方法,而且还具有其他灵活应用,后续会介绍到。
# `pandas` 是一个 `Python Data Analysis Library`。
# # 安装请参考官网的教程,如果安装了 `Anaconda`,则不需要安装 `pandas` 库。
#使用模块之前先导入
In[1]:
get_ipython().magic('matplotlib inline')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
pandas 基本数据结构
pandas 有两种常用的基本结构:
Series
一维数组,与Numpy中的一维array类似;二者与Python基本的数据结构List也很相近。Series能保存不同种数据类型,字符串、Boolean值、数字等。DataFrame
二维的表格型数据结构,很多功能与R中的data.frame类似;可以将DataFrame 理解为Series的容器。
1.2 Pandas库的series 类型
Series是一种类似与一维数组的对象,由下面两部分组成
values:一组数据(ndarray)
index:相关的数据索引标签
一维 `Series` 可以用一维列表初始化:
In[2]:
s = pd.Series([1,3,5,np.nan,6,8]) #np.nan代表空值
print(s)
0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64
默认情况下,Series的下标都是数字(默认索引为0到n-1的整形索引,可以使用额外参数指定),类型是统一的。可以使用index函数设置索引。
例如:
s = pd.Series([1,3,5,np.nan,6,8],index=['a','b','c','d','e','f'])
print(s)
a 1.0
b 3.0
c 5.0
d NaN
e 6.0
f 8.0
dtype: float64
索引-数据的行标签:
可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的是一个Series类型)
(1) 显式索引
使用index中的元素作为索引值
使用s.loc[](推荐):注意,loc中括号中放置的一定是显式索引
注意:此时是闭区间
(2)隐式索引:
使用整数作为索引值
使用.iloc[](推荐) iloc中括号中放置的必须是隐式索引
注意:此时是半开区间
In[ ]:
s.index
Index(['a', 'b', 'c', 'd', 'e', 'f'], dtype='object')
值
In[ ]:
s.values
array([ 1., 3., 5., nan, 6., 8.])
In[ ]:
display(
s[0],
s[3])
1.0
nan
切片操作:隐式索引切片和显式索引切片
显式索引切片:index和loc
隐式索引切片:整数索引值和iloc
In[ ]:
s[2:5]
c 5.0
d NaN
e 6.0
dtype: float64
In[ ]:
s[::2]
a 1.0
c 5.0
e 6.0
dtype: float64
索引赋值
In[ ]:
s.index.name = '索引'
S
索引
a 1.0
b 3.0
c 5.0
d NaN
e 6.0
f 8.0
dtype: float64
In[ ]:
s.index=list('abcdef')
s
a 1.0
b 3.0
c 5.0
d NaN
e 6.0
f 8.0
dtype: float64
In[ ]:
s['a':'c'] #这里的区间,全闭
a 1.0
b 3.0
c 5.0
dtype: float64
1.3 Pandas库的Data Frame 类型
Data Frame则是一个二维结构,这里首先构造一个时间序列,作为我们第一维的下标:
In[ ]:
dates = pd.date_range('0101', periods=6)
print(dates)
DatetimeIndex(['-01-01', '-01-02', '-01-03', '-01-04',
'-01-05', '-01-06'],
dtype='datetime64[ns]', freq='D')
然后创建一个 `DataFrame` 结构:
In[ ]:
df = pd.DataFrame(np.random.randn(6,4))
Df
In[ ]:
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
df
默认情况下,如果不指定 `index` 参数和 `columns`,那么他们的值将用从 `0` 开始的数字替代。
除了向 `DataFrame` 中传入二维数组,我们也可以使用字典传入数据:(只需要,要求同一列的数据类型相同)
In[ ]:
df2 = pd.DataFrame({'A':
1.,
'B'
:
pd.Timestamp('0102'),
'C'
:
pd.Series(1,index=list(range(4)),dtype='float32'),
'D'
:
np.array([3]
*
4,dtype='int32'),
'E'
:
pd.Categorical(["test","train","test","train"]),
'F'
:
'foo'
})
df2
字典的每个 `key` 代表一列,其 `value` 可以是各种能够转化为 `Series` 的对象。
与 `Series` 要求所有的类型都一致不同,`DataFrame` 值要求每一列数据的格式相同:
In[ ]:
df2.dtypes #查看数据类型
A float64
B datetime64[ns]
C float32
D int32
E category
F object
dtype: object
查看数据
头尾数据
head` 和 `tail` 方法可以分别查看最前面几行和最后面几行的数据(默认为 5):
In[ ]:
df.head()
#最后 3 行:
In[ ]:
df.tail(3)
下标,列标,数据
# 下标使用 `index` 属性查看:
In[ ]:
df.index
DatetimeIndex(['-01-01', '-01-02', '-01-03', '-01-04',
'-01-05', '-01-06'],
dtype='datetime64[ns]', freq='D')
# 列标使用 `columns` 属性查看:
In[ ]:
df.columns
Index(['A', 'B', 'C', 'D'], dtype='object')
# 数据值使用 `values` 查看:
In[ ]:
df.values
array([[ 1.2134, 0.69411908, 2.12508885, 0.98645103],
[-0.37277063, 0.80842712, 1.06651382, -1.17094025],
[ 0.04925703, -1.64894713, 1.02216368, 0.10823307],
[-0.86044928, 0.22772503, 1.1596821 , 1.2444777 ],
[-0.9035446 , -1.5242, -1.04663217, 0.06316338],
[-0.70521154, -0.93280946, 0.2882054 , -0.40130817]])
1.4 pandas读取数据及数据操作
这里以电影评分为例:(随机摘取):
In[ ]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.read_csv(r'file:///home/ccoy/Documents/homework/movies.csv') #读取数据
df.head(1)
行操作
In[ ]:
df.iloc[0]
电影名称 阿凡达5:追寻伊娃
主演 佐伊·索尔达娜/萨姆·沃辛顿/西格妮·韦弗/凯特·温丝莱特/奥娜·卓别林/史蒂芬·朗/乔·大...
导演 詹姆斯·卡梅隆
豆瓣评分 9.0
豆瓣投票数 1655
类型 动作/科幻/奇幻/冒险
片长 0
产地 美国
上映日期 2027/12/17
Name: 0, dtype: object
In[ ]:
df.iloc[0:2]
In[ ]:
df.loc[0:2] #loc是全闭区间,2在之类
添加一行
In[ ]:
dit={'电影名称':'复仇者联盟3','主演':'小罗伯特·唐尼','导演':'安东尼·罗素','豆瓣评分':8.7,'豆瓣投票数':153456,'类型':'剧情/科幻','片长':142,'产地':'美国','上映日期':'0504' }
s=pd.Series(dit)
s.name=140352 #变量最后一行数字加1
s #确认添加的数据
电影名称 复仇者联盟3
主演 小罗伯特·唐尼
导演 安东尼·罗素
豆瓣评分 8.7
豆瓣投票数 153456
类型 剧情/科幻
片长 142
产地 美国
上映日期 0504
Name: 140352, dtype: object
In[ ]:
df=df.append(s) #覆盖原来数据
df[-5:] #查看后五行
删除一行
In[ ]:
df=df.drop([140352]) #删除一行,使用drop方法
df[-5:]
列操作
In[ ]:
df.columns
Index(['电影名称', '主演', '导演', '豆瓣评分', '豆瓣投票数', '类型', '片长', '产地', '上映日期'], dtype='object')
In[ ]:
df['电影名称'] #查看‘电影名称’的值
0 阿凡达5:追寻伊娃
1 未定名新星球大战三部曲第三部
2 阿凡达4:祖古骑士
3 未定名星球大战项目2
4 阿凡达3:带种者
...
140347 Pretty Boy and Rosa - 电影
140348 番茄杀手 - 电影
140349 Fast Track - 电影
140350 7-9-13 - 电影
140351 大鱼 - 电影
Name: 电影名称, Length: 140352, dtype: object
In[ ]:
df['电影名称'][:3] #查看‘电影名称’前面3个的值
0 阿凡达5:追寻伊娃
1 未定名新星球大战三部曲第三部
2 阿凡达4:祖古骑士
Name: 电影名称, dtype: object
In[ ]:
df[['电影名称', '上映日期']][:3] #查看多列,需要以list格式
添加一列
In[ ]:
df['序号']=range(1,len(df)+1) #添加“序号”列,range自动添加,总数需要+1操作
df[:3]
删除一列
In[ ]:
df=df.drop('序号',axis=1) #删除“序号”列
df[-3:]
通过标签选择数据
df.loc[[index],[colunm]]通过标签选择数据
In[ ]:
df.loc[1,'电影名称'] #取出一行一列
'未定名新星球大战三部曲第三部'
In[ ]:
df.loc[[1,3,5,7,9],['电影名称','豆瓣评分']] #多行多列
条件选择
In[ ]:
df['产地']=='美国' #选取产地为美国的所有电影
0 True
1 True
2 True
3 True
4 True
...
140347 False
140348 False
140349 True
140350 False
140351 True
Name: 产地, Length: 140352, dtype: bool
In[ ]:
df[df['产地']=='美国'][:3] #选取产地为美国的所有电影,前3条
选取产地为美国的所有电影,并且评分大于9分的电影:
In[ ]:
df[(df.产地=='美国')&(df.豆瓣评分>9)][:3] #选取产地为美国的所有电影,前3条
选取产地为美国或中国大陆的所有电影,并且评分大于9分的电影:
In[ ]:
df[((df.产地=='美国')|(df.产地=='中国大陆'))&(df.豆瓣评分>9)][:3]
1.5 缺失值及异常值处理
缺失值处理方法
判断缺失值
In[ ]:
df.isnull() #是否是缺失的判断
140352 rows × 9 columns
In[ ]:
df['电影名称'].isnull() #确定列进行判断
0 False
1 False
2 False
3 False
4 False
...
140347 False
140348 False
140349 False
140350 False
140351 False
Name: 电影名称, Length: 140352, dtype: bool
In[ ]:
df[df['电影名称'].isnull()] #如果有缺失值,显示NaN
In[ ]:
df[df['豆瓣评分'].isnull()]
填充缺失值
In[ ]:
df['豆瓣评分'].fillna(np.mean(df['豆瓣评分']),inplace=True) #用所有电影评分均值进行填充
df[df.电影名称=='阿娜']
删除缺失值
df.dropna() 参数:
how=‘all’ :删除全为空值的行或列inplace=True :覆盖之前的数据axis=0(默认为行):选择行或列
In[ ]:
len(df) #在删除操作之前,先确定数据的数量
140352
In[ ]:
df.dropna(inplace=True)
len(df)
46238
处理异常值
异常值,即在数据集中存在不合理的值,又称之为离群点。比如年龄为-1,电脑的重量为1吨等,都属于异常值的范围。
In[ ]:
df[df.豆瓣评分==0][:3] #查看豆瓣评分为0的值
In[ ]:
df[df['豆瓣投票数']%1!=0] #查看豆瓣投票数有小数的值
df = df[df.豆瓣评分>0] #如果不是数据筛选,测试中不要操作
df = df['豆瓣投票数']%1==0 #如果不是数据筛选,测试中不要操作
对于异常值,一般来说数量都会很少,在不影响数据分布情况下,我们直接删除就可以了。
数据保存
In[ ]:
df.to_csv('电影修改.csv') #文件,将保存在当前文件夹
第二篇
2.1 数据格式转换
在做数据分析的时候,原始数据往往会因为各种各样的原因产生各种数据格式的问题。
数据格式是我们非常注意的一点,数据格式错误往往会造成严重的后果。并且,很多异常值也是我们经过格式转换之后才会发现,对我们规整数据、清洗数据有着重要的作用。
读取数据
In[ ]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.read_csv(r'file:///home/ccoy/Documents/homework/movies.csv') #读取数据
df[:5] #查看数据
查看格式
In[ ]:
df['豆瓣投票数'].dtype
dtype('float64')
In[ ]:
df.replace(np.nan, 0, inplace=True) #np.nan或者np.inf都是float的类型,而且无法转成int,会报错
df.replace(np.inf, 0, inplace=True) #可以,先把nan或者inf替换成0
df['豆瓣投票数']=df['豆瓣投票数'].astype('int') #转换为整数格式
df[:5] #查看数据
接下来,对“产地”转换格式为字符串“str”
In[ ]:
df['产地'].dtype #查看产地格式
dtype('O')
In[ ]:
df['产地']=df['产地'].astype('str') #转换为字符串格式
格式转换
将年份转化为整数格式
报错
将时长转化为整数格式
In[ ]:
df['片长']=df['片长'].astype('int') #转换为整数格式
2.2 排序
默认排序
In[ ]:
df[:5] #根据序列排序,也就是按照index进行
按照豆瓣投票数进行排序
In[ ]:
df.sort_values(by='豆瓣投票数')[-3:] #默认是升序排列
In[ ]:
df.sort_values(by='豆瓣投票数',ascending=False)[:3] #ascending=False,降序排列
按照上映时间进行排序
In[ ]:
df.sort_values(by='上映日期')[-8:-3]
多个值的排序,先按照豆瓣评分,再按照投票人数进行排序
In[ ]:
df.sort_values(by=['豆瓣评分','豆瓣投票数'],ascending=False)[:5]
2.3 基础统计分析
(1)描述性统计分析
DataFrame.describe(percentiles=None,include=None,exclude=None)
对dataframe中的数值型数据进行描述性统计分析,其物理意义在于观察这一系列数据的范围、大小、波动趋势等等,便于判断后续对数据采取哪类模型更合适。
In[ ]:
df.describe() #对数值型数据进行指标计算
通过描述性分析,可以发现一些异常值。
In[ ]:
df[df['片长']>1000]
对于异常值,可以通过其index判断,调用drop方法删除。
In[ ]:
df.drop(df[df['片长']>1000].index,inplace=True)
数据已经修改,序列也改变了,对index重新进行赋值!
In[ ]:
df.index = range(len(df))
(2)最值
In[ ]:
df['豆瓣投票数'].max() #最大值
1523334
In[ ]:
df['豆瓣投票数'].min() #最小值
0
(3)均值和中值
In[ ]:
df['豆瓣投票数'].mean() #均值
2561.845073533603
In[ ]:
df['豆瓣投票数'].median() #中位数
0.0
(4)方差和标准差
In[ ]:
df['豆瓣评分'].var() #方差
6.875473493358182
In[ ]:
df['豆瓣评分'].std() #标准差
2.622112410511453
(5)求和
In[ ]:
df['豆瓣投票数'].sum() #求和
359539585
(6)相关系数、协方差
In[ ]:
df[['豆瓣投票数','豆瓣评分']].corr() #相关性
In[ ]:
df[['豆瓣投票数','豆瓣评分']].cov() #协方差
(7)计数
In[ ]:
len(df) #计数,总数
140344
In[ ]:
len(df['产地'].unique()) #计数,唯一值的数量
4496
对于一些异常值,需要替换,比如一些国家的不同名称:
df['产地'].replace('USA','美国',inplace=True)
df['产地'].replace(['USA','苏联','西德'],['美国','俄罗斯','德国'],inplace=True) #注意,对应匹配
计算每一年的电影数量
比如,对上映时间的统计,也是一样:
In[ ]:
df['上映日期'].value_counts()
0 62649
/9/7 56
/9/8 50
/9/2 49
/9/9 48
...
1977/3/4 1
1973/4/2 1
1961/12/12 1
1946/10/30 1
1982/12/31 1
Name: 上映日期, Length: 22127, dtype: int64
电影产出前5的国家或地区:
In[ ]:
df['产地'].value_counts()[:5]
美国 36872
中国大陆 14050
日本 13672
英国 7956
法国 7426
Name: 产地, dtype: int64
2.4 数据透视
Excel中数据透视表的使用非常广泛了,其实Pandas也提供了一个类似的功能,名为pivot_table。
pivot_table非常有用,将重点解释padas中的函数pivot_table。
使用padas的pivot_table的一个挑战是,需要确保理解你的数据,并清楚的知道想通过透视表解决什么问题,虽然pivot_table看起来只是一个简单的函数,但它能够快速地对数据进行强大的分析。
1、基础形式
In[ ]:
pd.pivot_table(df,index = ['上映日期']) #根据上映日期做索引,均值
22127 rows × 3 columns
pd.set_option('max_columns',100) #允许最大输出列、行(设置)
pd.set_option('max_rows',500)
2、多个索引
In[ ]:
pd.pivot_table(df,index = ['上映日期','产地'])
58136 rows × 3 columns
3、指定统计汇总的数据
In[ ]:
pd.pivot_table(df,index = ['上映日期','产地'],values=['豆瓣评分'])
58136 rows × 1 columns
4、指定函数,统计不同的统计值
In[ ]:
pd.pivot_table(df,index=['产地','电影名称'],values=['豆瓣投票数'],aggfunc=np.sum)[-5:]
通过将“投票人数”和“评分”列进行对应分组,对“产地”实现数据聚合和总结。
In[ ]:
pd.pivot_table(df,index=['产地'],values=['豆瓣投票数','豆瓣评分'],aggfunc=[np.sum,np.mean])[-5:]
5、非数值(NaN)难以处理,使用“fill_value”将其设置为0
In[ ]:
pd.pivot_table(df,index=['产地'],aggfunc=[np.sum,np.mean],fill_value=0)
4493 rows × 6 columns
6、加入margins=True,可以在下方加入总和数据
In[ ]:
pd.pivot_table(df,index=['产地'],aggfunc=[np.sum,np.mean],fill_value=0,margins=True)
4494 rows × 6 columns
7、对不同值执行不同的函数,可以向aggfunc传递一个字典。不过,这样做有一个副作用,那就是必须将标签做的更加简洁才行。
In[ ]:
pd.pivot_table(df,index=['产地'],values=['豆瓣投票数','豆瓣评分'],aggfunc={'豆瓣投票数':np.sum,'豆瓣评分':np.mean},fill_value=0)
4493 rows × 2 columns
数据透视表过滤
In[ ]:
table1=pd.pivot_table(df,index=['产地'],values=['豆瓣投票数','豆瓣评分'],aggfunc={'豆瓣投票数':np.sum,'豆瓣评分':np.mean},fill_value=0)
type(table1)
pandas.core.frame.DataFrame
In[ ]:
table1[:5]
如果,我们对“美国”电影比较感兴趣
In[ ]:
table1[table1.index == '美国']
同样,对于豆瓣评分排序(降序):
In[ ]:
table1.sort_values('豆瓣评分',ascending=False)[:8]
同样,可以按照多个索引进行汇总。
第三篇
3.1 数据重塑和轴向旋转
1、层次化索引
层次化索引是pandas的一项重要功能,可以使我们在一个轴上拥有多个索引。
Series的层次化索引:
In[ ]:
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: int64
In[ ]:
s.index
MultiIndex([('a', 1),
('a', 2),
('a', 3),
('b', 1),
('b', 2),
('c', 3),
('c', 1),
('d', 2),
('d', 3)],
)
In[ ]:
s['a']
1 1
2 2
3 3
dtype: int64
In[ ]:
s['a':'c'] #切片
a 1 1
2 2
3 3
b 1 4
2 5
c 3 6
1 7
dtype: int64
内层选取
In[ ]:
s[:,1] #内层选取
a 1
b 4
c 7
dtype: int64
In[ ]:
s['c',3] #层次化索引
6
通过unstack方法将series变成DataFrame
通过stack方法复原
data.unstack().stack() #通过stack方法,可以将DataFrame变成Series,它是unstack的逆运算
2、DataFrame的层次化索引
对于DataFrame来说,行和列都能够进行层次化索引。
In[ ]:
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
In[ ]:
data['A']
In[ ]:
#对于dataframe,每条轴都可以分层索引,各层都可以有自己的名字的
data.index.names =["row1","row2"]
data.columns.names =["column1","column2"]
data
In[ ]:
#对"row1","row2"的顺序进行调整
data.swaplevel =["row1","row2"]
3、了解了层次化索引的基本认识之后,尝试将电影数据处理成多层索引结构
In[ ]:
df.index
RangeIndex(start=0, stop=140352, step=1)
把产地和年代同时设为索引,产地为外层索引,年代为内层索引
set_index
可以把列变为索引
In[ ]:
df=df.set_index(['产地','上映日期'])
df
140352 rows × 7 columns
reset_index
将索引变成列
每个索引都是一个元组
In[ ]:
df.index[0]
('美国', '2027/12/17')
获取所有的美国电影,因为产地已经成为索引,用.loc方法
In[ ]:
df.loc['美国']
36872 rows × 7 columns
In[ ]:
df = df.swaplevel('产地','上映日期')
df
140352 rows × 7 columns
获取/12/22的电影
In[ ]:
df.loc['/12/22']
取消层次化索引
使用reset_index()
函数
In[ ]:
df=df.reset_index()
df[:5]
4、数据旋转
dataframe可以使用stack和unstack,转化为层次化索引的series
行列转化:以前五部电影为例
In[ ]:
data=df[:5]
data
用.T操作可以使数据行列转换(类似于矩阵的转置)
In[ ]:
data.T
dataframe可以使用stack和unstack,转化为层次化索引的series
In[ ]:
data.stack()
0 上映日期 2027/12/17
产地 美国
电影名称 阿凡达5:追寻伊娃
主演 佐伊·索尔达娜/萨姆·沃辛顿/西格妮·韦弗/凯特·温丝莱特/奥娜·卓别林/史蒂芬·朗/乔·大...
导演 詹姆斯·卡梅隆
豆瓣评分 9.0
豆瓣投票数 1655.0
类型 动作/科幻/奇幻/冒险
片长 0.0
1 上映日期 2026/12/18
产地 美国
电影名称 未定名新星球大战三部曲第三部
导演 莱恩·约翰逊
豆瓣评分 6.0
豆瓣投票数 306.0
类型 动作/科幻
片长 0.0
2 上映日期 2025/12/19
产地 美国
电影名称 阿凡达4:祖古骑士
主演 佐伊·索尔达娜/萨姆·沃辛顿/西格妮·韦弗/史蒂芬·朗/凯特·温丝莱特/克利夫·柯蒂斯/奥娜...
导演 詹姆斯·卡梅隆
豆瓣评分 5.0
豆瓣投票数 22.0
类型 动作/科幻/奇幻/冒险
片长 0.0
3 上映日期 2024/12/20
产地 美国
电影名称 未定名星球大战项目2
豆瓣评分 8.0
豆瓣投票数 1895.0
类型 科幻
片长 0.0
4 上映日期 /12/22
产地 美国
电影名称 阿凡达3:带种者
主演 佐伊·索尔达娜/萨姆·沃辛顿/史蒂芬·朗/西格妮·韦弗/凯特·温丝莱特/克利夫·柯蒂斯/奥娜...
导演 詹姆斯·卡梅隆
豆瓣评分 8.0
豆瓣投票数 1660.0
类型 剧情/动作/科幻/奇幻/冒险
片长 0.0
dtype: object
如果要转回来:
data.stack().unstack()
3.2 数据分组,分组运算
GroupBy技术:实现数据的分组,分组运算,作用类似于数据透视表
按照电影的产地进行分组
先定义一个分组变量group
In[ ]:
group=df.groupby(df['产地']) #定义一个分组变量group'产地'
type(group) #查看类型
pandas.core.groupby.generic.DataFrameGroupBy
可以计算分组后的各个统计量
计算平均值
In[ ]:
group.mean()
4495 rows × 3 columns
计算各个上映日期的平均豆瓣评分
In[ ]:
df['豆瓣评分'].groupby(df['上映日期']).mean()
上映日期
1894-10-09 0.0
1906/12/26 0.0
1908/2/15 0.0
1909/1/1 0.0
1909/12/4 0.0
...
2024/11/30 0.0
2024/12/20 4.0
2025/12/19 5.0
2026/12/18 3.0
2027/12/17 9.0
Name: 豆瓣评分, Length: 22127, dtype: float64
由于groupby只会对数值变量进行分组运算,对于时间类型的数据,可以先把年代/日期/时间转换为字符串astype('str')
In[ ]:
df['上映日期']=df['上映日期'].astype('str')
df.groupby(df['产地']).mean() #求均值
4495 rows × 3 columns
In[ ]:
df.groupby(df['产地']).median() #求中值(中位数)
4495 rows × 3 columns
传入多个分组变量
In[ ]:
df.groupby([df['产地'],df['上映日期']]).mean()
58143 rows × 3 columns
获得每个地区,每个上映阶段的评分的均值
In[ ]:
group=df['豆瓣评分'].groupby([df['产地'],df['上映日期']])
means=group.mean()
means
产地 上映日期
Albania 1969/11/27 6.7
Albania / 德国 /11/1 0.0
Albania / 意大利 nan 0.0
Albania / 法国 / 德国 /5/14 0.0
Algeria / 法国 2002/10/1 0.0
...
黎巴嫩 / 法国 / 卡塔尔 /3/29 0.0
黎巴嫩 / 法国 / 卡塔尔 / 比利时 /9/1 7.3
黎巴嫩 / 法国 / 卡塔尔 / 阿联酋 /5/17 7.2
黎巴嫩 / 法国 / 塞浦路斯 / 比利时 / 美国 /8/31 8.3
黎巴嫩 / 法国 / 美国 /4/29 0.0
Name: 豆瓣评分, Length: 58143, dtype: float64
series通过unstack方法转化为DataFrame,没有数据会产生缺失值
In[ ]:
means.unstack().T
22128 rows × 4495 columns
3.3 离散化处理
在实际数据分析中,对某些数据我们往往并不关心数据的绝对取值,而只关心它所处的区间或等级。
比如可以把评分9分及以上的电影定义为A级,7—9分定义为B级等等
离散化也可以叫做分组,区间化,可以借助函数cut()实现
pd.cut()函数
pd.cut(x,bins,right=True,labels=None,retbins=False,precision=3,include_lowest=False)
参数解释:
x:需要离散化的对象,一般为数值,series,Dataframe对象
bins:分组的依据
right:左区间开闭情况
include_lowest:右区间开闭情况
labels:是否用标记替代分组取值
retbins:返回x对应的bins的列表
precision:设置精度
用评分等级将数据分组
In[ ]:
labels=['E','D','C','B','A']
df['评分等级']=pd.cut(df['豆瓣评分'],[0,3,5,7,9,10],labels=['E','D','C','B','A'])
df
140352 rows × 10 columns
根据投票人数来刻画电影热门
同样可以根据投票人数来刻画电影热门,投票越多的热门程度越高
In[ ]:
bins=np.percentile(df['豆瓣投票数'][:20],[0,20,40,60,80,100]) #由于数据库原因,只能选择部分,选择前20条为例
df['热门程度']=pd.cut(df['豆瓣投票数'][:20],bins,labels=['E','D','C','B','A'])
df[:3]
关于numpy.percentile()
函数:
百分位数是统计中使用的度量,表示小于这个值的观察值的百分比。 函数numpy.percentile()接受以下参数。
np.percentile(a, q, axis=None, out=None, overwrite_input=False, interpolation='linear', keepdims=False)
a: 输入数组
q: 要计算的百分位数,在 0 ~ 100 之间
axis: 沿着它计算百分位数的轴
keepdims :bool是否保持维度不变
首先明确百分位数:第 p 个百分位数是这样一个值,它使得至少有 p% 的数据项小于或等于这个值,且至少有 (100-p)% 的数据项大于或等于这个值。
比如:
import numpy as np
a = np.array([[10, 7, 4], [3, 2, 1]])
print ('我们的数组是:')
print (a)
print ('调用 percentile() 函数:')
# 50% 的分位数,就是 a 里排序之后的中位数
print (np.percentile(a, 50))
# axis 为 0,在纵列上求
print (np.percentile(a, 50, axis=0))
# axis 为 1,在横行上求
print (np.percentile(a, 50, axis=1))
# 保持维度不变
print (np.percentile(a, 50, axis=1, keepdims=True))
离散化数据的应用:
找出大烂片!
大烂片:投票人数很多,但评分很低
In[ ]:
df[(df['热门程度']=='A')&(df['评分等级']=='E')]
找出高分冷门电影!
In[ ]:
df[(df['热门程度']=='E')&(df['评分等级']=='A')]
合并数据集
1. append()方法
先把数据集拆分为多个,再进行合并
In[ ]:
df_usa=df[df.产地=='美国']
df_china=df[df.产地=='中国大陆']
df_china.append(df_usa)
50922 rows × 11 columns
将这两个数据集进行合并!
merge()方法
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
)
作为一个功能完善、强大的语言,python的pandas库中的merge()支持各种内外连接。
left与right:两个不同的DataFramehow:指的是合并(连接)的方式有inner(内连接),left(左外连接),right(右外连接),outer(全外连接);默认为inneron : 指的是用于连接的列索引名称。必须存在右右两个DataFrame对象中,如果没有指定且其他参数也未指定则以两个DataFrame的列名交集做为连接键left_on:左则DataFrame中用作连接键的列名;这个参数中左右列名不相同,但代表的含义相同时非常有用。right_on:右则DataFrame中用作 连接键的列名left_index:使用左则DataFrame中的行索引做为连接键right_index:使用右则DataFrame中的行索引做为连接键sort:默认为True,将合并的数据进行排序。在大多数情况下设置为False可以提高性能suffixes:字符串值组成的元组,用于指定当左右DataFrame存在相同列名时在列名后面附加的后缀名称,默认为('_x','_y')copy:默认为True,总是将数据复制到数据结构中;大多数情况下设置为False可以提高性能indicator:在 0.17.0中还增加了一个显示合并数据中来源情况;如只来自己于左边(left_only)、两者(both)
选6部热门电影
In[ ]:
df1=df.loc[:5]
df1
In[ ]:
df2=df.loc[:5][['电影名称','产地']]
df2['票房']=[123456,123545,486213,45684,1213546,15484]
df2
In[ ]:
df2=df2.sample(frac=1)
df2
此时,索引对不上了...
现在,我们如何将df1和df2合并?
In[ ]:
pd.merge(df1,df2,how='inner',on='电影名称')
因为两个集都存在产地,故合并后有两个产地信息
3. concat()方法
可将多个数据集进行批量合并
In[ ]:
df1=df[:10]
df2=df[100:110]
df3=df[200:210]
dff=pd.concat([df1,df2,df3]) #axis默认为0,在行上进行修改,为1,在列上进行修改
dff
仅供参考学习,严禁转载!