python数据分析三剑客之pandas
pandas简介:
Python Data Analysis Library或pandas是基于NumPy的一种工具,该工具是为了解决数据分析任务而创建的。Pandas纳入了大量库和一些标准的数据模型,提 l供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
导入: import pandas as pd
pandas数据类型:
pandas的series类型:
一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近。Series能保存不同种数据类型,字符串、boolean值、数字等都能保存在Series中。
**初始化(s要大写)😗*pd.Series()
默认下标是数字可以通过index参数修改下标
也可以通过index函数修改下标:a.index=list(‘abc’)
可以通过index函数来查看下标:
给索引取名:
查看Series:
其他的索引与切片和列表差不多
注意:如果索引不是数字,切片时就不是左闭右开[),而是闭区间[]
dataframe类型:
二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。以下的内容主要以DataFrame为主。
创造一组时间序列:
a = pd.date_range('20230520',periods=9)
a
DatetimeIndex(['2023-05-20', '2023-05-21', '2023-05-22', '2023-05-23',
'2023-05-24', '2023-05-25', '2023-05-26', '2023-05-27',
'2023-05-28'],
dtype='datetime64[ns]', freq='D')
构造dataframe:
可以通过index和columns指定行和列的名字:
dataframe可以通过字典来创建: 字典的键就是columns,值就是数据,但是每一列的数据数量必须相等
b=pd.DataFrame({'a':1.5,'B':pd.Timestamp('20230426'),'1':3,'C':pd.Series([2,3,4,5]),'D':np.array([1,2,3,4])})
查看数据:
b.head() 和 b.tail():默认为查看前五行(后五行)
b.dtypes :查看每一列的数据类型
b.index : 查看下标
b.columns : 查看列
b.values : 查看表中的数据
pandas关于数据的操作:
pd.read_excel(‘路径’) :读取Excel表格
pd.read_csv(‘路径’):读取csv文件
如果在同一路径直接写文件名,否则写绝对路径
df = pd.read_excel('pandas基础操作.xlsx')
df.head()
行操作:
查看行(iloc,loc):
iloc:
查看索引为0的一行:
查看前五行:
loc:
和iloc不同,loc是个全闭区间
注意:也可以使用切片来查看数据:
添加行:
首先需要创建一个字典来存储数据,再转化为Series,最后通过append添加一行
注意:会创建一个新对象,需要重新赋值,需要看最后一行的index,将新的行的index赋值
t = {'名字':'复仇者联盟3','投票人数':123445,'类型':'剧情/科幻','产地':'美国','上映时间':'1989-9-9 00:00:00','时长':180,'年代':1989,'评分':9.6,'首映地点':'美国'}
t = pd.Series(t)
t.name = 26
df = df.append(t)
df.tail(1)
# append方法在新版中已被弃用,用pd.concat()替代
# pandas.concat()通常用来连接DataFrame对象。默认情况下是对两个DataFrame对象进行纵向连接, 当然通过设置参数(ignore_index=True),也可以通过它实现DataFrame对象的横向连接。
# pd.concat([这里必须是个列表])
t = {'名字':'复仇者联盟','投票人数':123445,'类型':'剧情/科幻','产地':'美国','上映时间':'1989-9-9 00:00:00','时长':180,'年代':1989,'评分':9.6,'首映地点':'美国'}
t = pd.DataFrame(t,index=[26])
df = pd.concat([df,t])
df.tail()
删除行:
df.drop(索引)
# 返回的是删除这一行后的dataframe,所以要删除必须重新赋值
df = df.drop(26)
列操作:
查看列:
查看所有列名:
df.columns
查看前五列名:
df.columns[:5]
查看某一列数据中的前五条:
df['名字'][:5]
# 0 肖申克的救赎
# 1 控方证人
# 2 美丽人生
# 3 阿甘正传
# 4 肖申克的救赎
查看某几列的前五条:
df[['名字','评分']][:5]
增加列:
增加一列:
df['列名'] = 值
# 例:增加一列序号
# df['序号'] = None
删除列:
# drop默认axis=0,代表的是行,改为1代表的就是列了
df = df.drop('序号',axis=1)
取数据:
Unnamed: 0 名字 Unnamed: 2 投票人数 类型 产地 上映时间 Unnamed: 7 Unnamed: 8 时长 年代 评分 首映地点
0 0 肖申克的救赎 NaN 989899 剧情/犯罪 美国 1994-09-10 NaN NaN 142 1994 9.6 多伦多电影节
1 1 控方证人 NaN 42132 剧情/悬疑 美国 1957-12-17 NaN NaN 116 1957 9.5 美国
2 2 美丽人生 NaN 323233 剧情/喜剧 意大利 1997-12-20 NaN NaN 116 1997 9.5 意大利
3 3 阿甘正传 NaN 580897 剧情/爱情 美国 1994-06-23 NaN NaN 142 1994 9.4 洛杉矶
4 4 肖申克的救赎 NaN 989899 剧情/犯罪 美国 1994-09-10 NaN NaN 142 1994 9.6 多伦多电影节
取出控方证人:
df.loc[1,'名字']
取出第三行的名字以及评分:
df.loc[3,['名字','评分']]
取出前三行的名字和评分:
df.loc[:3,['名字','评分']]
取出所有美国的电影的前五个:
# 列名可以直接用.来调用
# df.产地=='美国' : 返回True和False
df[df.产地=='美国'][:5] # 所有是True的数据拿出来
取出产地为美国并且评分高于9.5的电影:
df[(df.产地=='美国') & (df.评分>9.5)]
取出产地为美国或者意大利并且评分高于9.5的电影:
df[((df.产地=='美国') | (df.产地=='意大利')) & (df.评分>9.5)]
关于缺失值的操作:
方法 | 说明 |
---|---|
dropna | 根据标签中的缺失值进行过滤,删除缺失值 |
fillna | 对缺失值进行填充 |
isnull | 判断是空 |
notnull | 判断不是空 |
求多少缺失值
df.isna().sum().sum()
df.isna() 返回true false
df.isna().sum() 返回每一列的空的true false
df.isna().sum().sum() 总共多少个缺失值
查看所有有缺失值的一行
df[df.isnull().T.any()==True]
高亮缺失值
(df[df.isnull().T.any() == True]
.style
.highlight_null(null_color='skyblue'))
判断空:
# 查找所有名字为空的数据
df[df['名字'].isnull()]
填充缺失值:
# 将所有名字为空的电影名字改为未知电影
df = df['名字'].fillna('未知电影')
# 可以通过inplace参数直接修改原数据
df['名字'].fillna('未知电影',inplace=True)
# 将缺失值填充为上一个电影评分
df['评分'] = df['评分'].fillna(axis=0,method='ffill')
# 将缺失值填充为整列的均值
df['评价人数'] = df['评价人数'].fillna(df['评价人数'].mean())
# 将缺失值填充为上下的均值
df['评价人数'] = df['评价人数'].fillna(df['评价人数'].interpolate())
# 将语言缺失值根据国家/地区来填充
df['语言'] = df.groupby('国家/地区').语言.bfill()
删除缺失值:
# dropna参数: how='all':删除全部为空的行和列, inplace:直接对原数据操作, axis:操作行和列
# 删除所有有一个数据为空的行
df.dropna()
查找所有重复的数据
# 所有数据都一样
df[df.duplicated()]
# 查找片名重复
df[df.duplicated(['片名'])]
删除重复数据
# 删除全部重复数据
df = df.drop_duplicates()
# 删除所有重复数据但保留最后一个数据
df = df.drop_duplicates(keep = 'last')
异常值:
在不影响数据整体分布的情况下,异常值可以直接删去
# 删除投票人数为负数和小数的数据
df = df[df.投票人数>0]
df = df[(df.投票人数)%1 == 0]
数据保存
df.to_excel('路径')
数据类型格式转换:
查看数据类型:
df['投票人数'].dtype()
修改数据类型:
df['投票人数'] = df['投票人数'].astype('int')
处理异常数据:
# 根据报错提示,找到异常数据,如果知道原始数据,就可以使用loc修改,如果不知道就直接删去
df['年代'].astype('int')
# 假如这个报错了
# 先查看那一行报错数据
df[df.年代=='报错信息']
# 做出修改或者删除
df.loc[下标,columns] = 新值 || df.drop(下标,inplace=True)
排序:
单值排序
# 默认是按照下标来进行排序
# 按照投票人数进行升序排列
df.sort_values(by='投票人数')
# 降序排列
df.sort_values(by='投票人数',ascending=False)
多值排序
df.sort_values(by=['投票人数','评分'])
基本统计分析
描述性统计
df.describe()
# Unnamed: 0 Unnamed: 2 投票人数 Unnamed: 7 Unnamed: 8 时长 年代 评分
# count 26.000000 0.0 26.000000 0.0 0.0 26.000000 26.000000 26.000000
# mean 12.500000 NaN 491490.769231 NaN NaN 130.000000 1986.153846 9.492308
# std 7.648529 NaN 342684.476575 NaN NaN 13.218169 16.330811 0.074421
# min 0.000000 NaN 42132.000000 NaN NaN 116.000000 1957.000000 9.400000
# 25% 6.250000 NaN 323233.000000 NaN NaN 116.000000 1994.000000 9.400000
# 50% 12.500000 NaN 580897.000000 NaN NaN 142.000000 1994.000000 9.500000
# 75% 18.750000 NaN 580897.000000 NaN NaN 142.000000 1994.000000 9.500000
# max 25.000000 NaN 989899.000000 NaN NaN 142.000000 1997.000000 9.600000
通过描述性统计,可以发现一些异常数据,对异常数据进行操作
# 删除年代大于2023的电影
df.drop(df[df.年代>2023].index,inplace=True)
# 删除时长大于1000的电影
df.drop(df[df.时长>1000].index,inplace=True)
# 删除数据后index就变得不连续了,所以需要重新赋值index
df.index = range(len(df))
# 最值
df['评分'].max()
df['评分'].min()
# 均值和中值
df['评分'].mean()
df['评分'].median()
# 方差和标准差
df['方差'].var()
df['标准差'].std()
# 求和
df['评分'].sum()
# 相关系数 协方差
df[['投票人数','评分']].corr()
df[['投票人数','评分']].cov()
# 计数
# 总共多少电影
len(df)
# 电影来自多少个国家
len(df['产地'].unique())
产地中包含美国,USA,德国,西德,俄罗斯,苏联,这时候就需要用到数据替换了
数据替换
df['产地'].replace('USA','美国',inplace=True)
df['产地'].replace(['西德','苏联'],['德国','俄罗斯'],inplace=True)
计算每一年的电影数量
# 默认按照数量降序排列
df['年份'].value_counts()
查看某些列最高分的索引
# 返回分数最高的一个索引
df.iloc[:,'分数'].idxmax()
查看某些列的某些聚合属性
# 查看某些列的最小最大值,中位数,均值
df.agg({
"总分": ["min", "max", "median", "mean"],
"高端人才得分": ["min", "max", "median", "mean"],
"办学层次得分":["min", "max", "median", "mean"]})
数据透视
pd.pivot_table(ad,index=)
pd.pivot_table(df,index=['年代'])
# 会把每个年代的各种数据的均值计算出来
# 年代 Unnamed: 0 投票人数 时长 评分
# 1957 24.500000 42132.000000 116 9.500000
# 1994 25.928571 756183.571429 142 9.485714
#1997 25.500000 323233.000000 116 9.500000
# 如果数据太多了jupyter会自动折叠,可以通过set_option来设置
# 设置最大展现行数300行,100列
pd.set_option('max_columns',100)
pd.set_option('max_rows',300)
index
pd.pivot_table(df,index=['年代','评分'])
# 年代 评分 Unnamed: 0 投票人数 时长
# 1957 9.5 24.50 42132 116
# 1994 9.4 27.75 580897 142
# 9.6 23.50 989899 142
# 1997 9.5 25.50 323233 116
values
pd.pivot_table(df,index=['年代','评分'],values=['投票人数'])
# 年代 评分 投票人数
# 1957 9.5 42132
# 1994 9.4 580897
# 9.6 989899
# 1997 9.5 323233
aggfunc
# 对投票人数进行求和
pd.pivot_table(df,index=['年代','评分'],values=['投票人数'],aggfunc=np.sum)
# 对投票人数分布进行求和 和 求均值
pd.pivot_table(df,index=['年代','评分'],values=['投票人数'],aggfunc=[np.sum,np.mean])
# 通过字典对投票人数和时长进行分别设置
pd.pivot_table(df,index=['年代'],values=['投票人数','时长'],aggfunc={'投票人数':np.sum,'时长':np.mean})
fill_value
# 将空数据设置为0
pd.pivot_table(df,index=['年代','评分'],values=['投票人数'],aggfunc=[np.sum,np.mean],fill_value=0)
margins
# 在最下方添加一行总和
pd.pivot_table(df,index=['年代','评分'],values=['投票人数'],aggfunc=[np.sum,np.mean],fill_value=0,margins=True)
pivot_table返回的也是个dataframe,因此,可以使用个变量来接收dataframe,然后dataframe的方法都能使用
数据重塑和轴向旋转
层次化索引
Series的层次化索引
# 创建Series对象
df = 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]])
# a 1 1
# 2 2
# 3 3
# b 1 4
# 2 5
# c 3 6
# 1 7
# d 2 8
# 3 9
# dtype: int32
# 查看下标 df.index
MultiIndex([('a', 1),
('a', 2),
('a', 3),
('b', 1),
('b', 2),
('c', 3),
('c', 1),
('d', 2),
('d', 3)],
)
# 使用方法和二维差不多
# 取出所有外层索引&内层索引=1的值
df[:,1]
# 取出a~c
df['a':'c']
# 取出c,3
df['c',3]
# 还可以把Series变成Dataframe
df.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
# 可以通过stack堆叠变为Series
df.stack()
DataFrame的层次化索引
df = pd.DataFrame(np.arange(12).reshape(4,3),index=[['a','a','b','b'],[1,2,1,2]],columns=[['A','A','B'],['C','D','E']])
# 给行和列取名
df.index.names=['row1','row2']
df.columns.names=['col1','col2']
# 换位置
df.swaplevel('row1','row2')
# set_index columns变为index
df = df.set_index(['年代','产地'])
# 使用loc
# 拿到所有index为美国的电影
df.loc['美国']
# reset_index 将index变为columns
df = df.reset_index()
数据旋转
转置
# 行和列交换位置
df.T
堆叠
# 也能使用stack和unstack
# 将DataFrame堆叠为一维
df.stack()
分组
groupby
# 根据产地分组并求均值
df.groupby(df['产地']).mean()
# 计算每年的平均分
df['评分'].groupby(df['年代']).mean()
# 只会对数值进行运算,所以不想年份参与运算可以这样
df['年代'] = df['年代'].astype('str')
# 每个产地每个年代的均值
df.groupby([df['产地'],df['年代']]).mean()
# 每个产地每一年的评分均值
df['评分'].groupby([df['产地'],df['年代']]).mean()
离散化
pd.cut(x,bins,right=True,labels=None,retbins=False,percision=3,include_lowest=False)
# x 数组,Series,DataFrame
# bins 分组区间
# labels 区间名
# right 包不包括右端点
# include_lowest 包不包括左端点
# 根据评分离散化
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'])
# 根据投票人数确定电影热门程度
# np.percentile(数据,[百分比的几等分])
bins = np.percentile(df['投票人数'],[0,20,40,60,80,100])
df['热门程度']pd.cut(df['投票人数'],bins,labels=['E','D','C','B','A'])
# 寻找大烂片
df[(df.评分=='E')&(df.热门程度=='A')]
合并数据集
append : 尾部连接
merge
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 连接方式 inner 内连接:交集 left:左连接 right:右连接
# on 要加入的列名(通过他来进行连接)必须要两个里面都有这一列
# left_on right_on 如果两个里面都没有相同的数据,就可以通过left_on 和 right_on 来指定以那一列做合并
# sort 按照字典序排序 设置为False可以极大提升性能2
# suffixes 如果两个Dataframe都有产地,合并后就会有产地_x,产地_y
# 合并df1 df2
df1 = df.loc[:5]
df2 = df.loc[:5]
# 给df2增加一列
df2['票房'] = [111,22,333,444,555,666]
# 打乱df2
df2 = df2.sample(frac=1)
# 回复index
df2.index=range(len(df2))
# 合并
pd.merge(df1,df2,how='inner',on='名字')
concat
# 合并多个数据集
df1 = df[:5]
df2 = df[10:15]
df3 = df[20:25]
# 默认是尾部拼接
x = pd.concat([df1,df2,df3])
# 修改axis参数可以实现纵向拼接
x = pd.concat([df1,df2,df3],axis=1)