Pandas
Pandas库基于Numpy库,提供很多用于数据操作与分析功能
pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。它是使Python成为强大而高效的数据分析环境的重要因素之一。
安装与使用
安装: pip install pandas | conda install pandas
使用: import pandas as pd
两个常用数据类型
pandas提供两个常用数据类型
- Series
- DataFrame
import pandas as pd
import numpy as np
Series类型
Series类型类似numpy的一维数组,可将此类型看做一组数据与数据相关标签(索引)联合构成。
创建方式
- 列表等可迭代对象
- ndarray数组对象
- 字典对象
- 标量
# Series 带标签的一维数组
# 使用列表创建
# s = pd.Series([1,2,3])
# 使用可迭代对象
# s=pd.Series(range(5))
# ndarray数组对象
# s=pd.Series(np.array([1,2,3]))
# 字典数据,Series对象的标签为字典数据中key
# s=pd.Series({'a':1,'b':2,'c':3})
# 标量,使用index参数指定索引
s=pd.Series(33,index=['a','b','c'])
display(s)
相关属性
- index
- values
- shape
- size
- dtype
Series对象可以通过index与values访问索引与值
说明:
- 如果没有指定索引,则会自动生成从0开始后的整数值索引,也可以使用index显式指定索引
- Series对象与index同样有name属性,Series的name属性可在创建时通过name参数指定。
- 当数值较多时,可以通过head和tail访问前后N个数据
- Sereis对象的数组只能是一维数组类型
# s = pd.Series([1,2,3])
s = pd.Series([1,2,3],index=list('abc'))
# 返回元素索引
display(s.index)
# 返回元素的值
display(s.values,type(s.values))
# 返回元素的形状
display(s.shape)
# 返回元素个数
display(s.size)
# 返回元素数据类型
display(s.dtype)
s = pd.Series([1,2,3],index=list('abc'))
s.name='Sereis name'
s.index.name='index name'
display(s)
ind = pd.Index(['a','b','c'],name='index name')
s = pd.Series([1,2,3],index=ind,name='Series name')
display(s)
s = pd.Series(np.arange(1000))
# head查看前面数据,默认5条;tail查看后面的数据,默认是5条
# display(s.head(),s.tail())
display(s.head(3),s.tail(3))
# 只能传入一维数据
s = pd.Series(np.array([[1,2],[2,3]])) # 会报错
s
Series和ndarray索引访问比较
Series对象可以看做带标签的ndarray,其中标签和值类似字典的key和value,不支持负数
s = pd.Series([1,2,3])
# display(s)
# display(s[0])
# Series类似于字典的key和value方式,不支持负数访问
# display(s[-1]) # 会报错
# ndarray类似于list索引,支持负数访问
x = np.array([1,2,3])
display(x[-1])
Series相关操作
Sereis在操作上与ndarray类似
- 支持广播与向量化运算
- 支持索引与切片
- 支持整数数组与布尔数组提取元素运算
Numpy统计函数也适用于Sereis类型,例如 np.mean,np.sum等。多个Sereis运算时,会根据索引进行对齐。当索引无法匹配时,结果值为NaN(缺失值) 说明
- pandas或Sereis的isnull与notnull判断数据是否缺失
- Sereis对象可以使用运算符运算,也可以使用Sereis对象提供相关方法进行运算(指定缺失值的填充值)
- Sereis和Numpy对于空值(NaN)计算方式上不同。Numpy会处理NaN,而Sereis忽略NaN
# Series和ndarray类似,也支持广播和向量化整体操作
s = pd.Series([1,2,3])
s2 = pd.Series([2,3,4])
# display(s*s2)
display(s*2)
s = pd.Series([1,2,3],index=[1,2,3])
s2 = pd.Series([2,3,4],index=[2,3,4])
# Series运算时候,根据标签进行匹配,如果是不一致,产生空值
# 空值和任何其他的值运算还是空值 np.nan/3=nan
display(s*s2)
np.nan/3
s = pd.Series([1,2,3],index=[1,2,3])
s2 = pd.Series([2,3,4],index=[2,3,4])
# 如果Series对象运算结果不想要空值,可以使用Sereis对象提供计算方法得到
s.add(s2,fill_value=10)
s = pd.Series([1,2,3,float('NaN'),np.nan])
# 判断数据是否为空值
# display(s.isnull())
# 判断数据不是为空值
# display(s.notnull())
display(pd.notnull(s))
# 在统计函数中,numpy处理NaN,Sereis忽略Nan
a = np.array([1,2,3,np.nan])
s = pd.Series([1,2,3,np.nan])
display(np.mean(a))
display(np.mean(s))
索引
标签索引与位置索引
当Sereis对象的index值为非数值类型,可以使用标签和位置索引,也可以显式指定标签或者位置索引访问
- loc标签索引访问
- iloc位置索引访问
标签、位置数组索引与布尔数组索引
Sereis支持标签、位置数组索引与布尔数组索引,返回是原数据的拷贝
# s = pd.Series([1,2,3])
# display(s[0])
# 通过index指定标签信息,非数值类型标签信息
# Sereis对象既可以通过标签索引来访问,也可以通过位置索引来访问
s = pd.Series([1,2,3],index=list('abc'))
display(s['a'])
display(s[0])
# 通过index指定标签信息,数值类型标签信息
# 当指定索引是数值类型时候,位置索引失效
s = pd.Series([1,2,3],index=[2,3,4])
display(s[2])
# 错误
# display(s[0])
# Sereis对象提供iloc和loc来显式访问位置和标签索引
s = pd.Series([1,2,3],index=list('abc'))
# loc专门来通过标签进行访问
display(s.loc['a'])
# iloc专门来通过位置进行访问
display(s.iloc[0])
# 我们通过标签或位置数组来访问多个元素
s = pd.Series([1,2,3],index=list('abc'))
display(s.loc['a'])
display(s.loc[['a','c']])
display(s.iloc[[0,2]])
# 通过标签或位置数组来访问多个元素得到是原数据拷贝,彼此间不会互相干扰
s = pd.Series([1,2,3],index=list('abc'))
s2 = s.loc[['a','c']]
display(s,s2)
s2['a']=100
display(s,s2)
# 布尔数组索引访问Sereis中数据
s = pd.Series([1,2,3,4],index=list('abcd'))
display(s>2)
display(s[s>2])
切片
Series和ndarray数组一样支持切片访问多个元素,返回的数据和原数据共享内存
# Series对象和ndarray数组一样支持切片操作,且返回的数据和原数据共享内存
s = pd.Series([1,2,3,4])
s2 = s[0:3]
display(s2)
# 共享内存,修改其中一方会影响另外一方
s2[0] = 100
display(s2,s)
# Sereis具有标签索引和位置索引,通过连着访问多个数据
s = pd.Series([1,2,3,4],index=list('abcd'))
# 位置索引切片访问,不包含终止值
display(s.iloc[0:3])
# 标签索引切片访问,包含终止值
display(s.loc['a':'d'])
Series增删改查操作
s = pd.Series([1,2,3,4],index=list('abcd'))
# 获取值,通过标签或者位置索引(或者2者数组)
display(s.loc['a'])
display(s.iloc[0])
# 修改值
s.loc['a']=100
# 增加值,类似字典操作
s['f']=5
display(s)
# 删除值,类似字典操作
# del s['f']
# display(s)
# 删除值,drop,inplace为false
# inplace为false,根据原有的Series对象数据复制得到新的Sereis,对新的Sereis对象删除数据并将其返回
# s2 = s.drop('f')
# display(s,s2)
# inplace为True,删除的就是原有Sereis对象的数据,并且drop方法返回None
# s2 = s.drop('f',inplace=True)
# display(s,s2)
# 删除多个值,drop
s.drop(['a','f'],inplace=True)
display(s)
DataFrame介绍
DataFrame类似数据库中数据表,多列构成,每列类型不同。 DataFrame二维数据类型,具有行,列索引。 DataFrame从每一列来看,是一个Series;从每一行来看,也是一个Sereis
DataFrame创建
我们可以使用如下方式创建DataFrame
- 二维数据结构类型(列表,ndarray数组,DataFrame等)
- 字典类型,key列名,value为一维数组结构(列表,ndarray数组,Sereis等)
# 使用二维的数据结构类型(ndarray,列表)
# df = pd.DataFrame(np.array([[100,100,100],[90,90,90],[80,80,80]]))
# df = pd.DataFrame([[100,100,100],[90,90,90],[80,80,80]])
# # print(df)
# display(df)
# 使用字典创建,key就是列名,value一维数据结构
df = pd.DataFrame({'语文':[100,100,100],'数学':[90,90,90],'外语':[80,80,80]})
display(df)
# 未通过index columns指定行索引和列索引,行索引和列索引默认从0开始
# index指定行索引
df = pd.DataFrame([[100,100,100],[90,90,90],[80,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
DataFrame属性
- index
- columns
- values
- shape
- ndim
- dtypes
df = pd.DataFrame([[100,100,100],[90,90,90],[80,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
# 返回行索引
display(df.index)
# 返回列索引
display(df.columns)
# 返回DataFrame对象对应ndarray数组
display(df.values)
# 返回形状
display(df.shape)
# 返回维度
display(df.ndim)
# 返回各列数据类型
display(df.dtypes)
# 通过index修改行索引信息
# df.index=['张三2','李四2','王五2']
# display(df)
# 设置行索引和列索引名称
df.index.name='index-name'
df.columns.name='columns-name'
display(df)
# 超过二维数据创建DataFrame 报错
df = pd.DataFrame(np.arange(18).reshape(2,3,3))
display(df)
DataFrame列操作
获取列数据
- df[列索引]
- df.列索引
增加(修改)列
- df[列索引]=列数据
删除列
- del.df[列索引]
- df.pop(列索引)
- df.drop(列索引或数组)
df = pd.DataFrame([[100,100,100],[90,90,90],[80,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# 获取列数据,通过df[列索引]
# 注意,此种方式索引被解析成列索引,获取列数据,不会解析成行索引
# display(df['语文'],type(df['语文']))
# 获取多列数据, df[索引数组]
display(df[['语文','数学']],type(df[['语文','数学']]))
# 如果索引数组中索引只有一个列标签,返回的仍然是DataFrame类型
display(df[['语文']],type(df[['语文']]))
# 第二种方式访问列数据,不推荐
display(df.语文)
df = pd.DataFrame([[100,100,100],[90,90,90],[80,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# 增加、修改列
# 列标签不存在话,增加一列
# df['物理']=[80,80,80]
# display(df)
# 根据已有列计算,得到新的一列
df['总分']=df['语文']+df['数学']+df['外语']
display(df)
# 列标签存在话,修改一列
# df['语文']=[80,80,80]
# display(df)
df = pd.DataFrame([[100,100,100],[90,90,90],[80,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# 删除列,采用类似字典方式 del pop
# del df['语文']
# display(df.pop('语文'))
# display(df)
# DaraFrame提供drop方法删除,
df.drop('数学',axis=1,inplace=True)
display(df)
DataFrame行操作
获取行
- df.loc 根据标签进行索引
- df.iloc根据位置进行索引
增加行
- append
删除行
- df.drop
df = pd.DataFrame([[100,100,100],[90,90,90],[80,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# df.loc 标签索引
display(df.loc['张三'],type(df.loc['张三']))
# df.iloc 位置索引
# display(df.iloc[0])
# 多行获取
# display(df.loc[['张三','李四']])
# 增加行数据
# 创建一个Sereis对象,Sereis对象通过append方法加入到DataFrame中
# Sereis对象包含 value信息,index信息,name信息
newLine= pd.Series([85,85,85],index=['语文','数学','外语'],name='赵六')
df = df.append(newLine)
display(df)
# 删除行数据
df.drop(['张三','李四'],axis=0,inplace=True)
display(df)
DataFrame混合操作
- 先获取行,再获取列
- 先获取列,再获取行
df = pd.DataFrame([[100,100,100],[90,90,90],[86,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# 先获取行,再获取列
# display(df.loc['张三'].loc['语文'])
# display(df.loc['张三']['语文'])
# display(df.loc['张三','语文'])
# 先获取列,再获取行
display(df['语文'].loc['张三'])
display(df['语文']['张三'])
# 错误,不支持
# display(df['语文','张三'])
DataFrame结构
DataFrame的一行或一列,都是Sereis类型对象。对于行来说,Series对象name值就是行索引名称,元素值对应标签是列索引名称。对于列来说,Series对象name值就是列索引名称,元素值对应标签是行索引名称。
df = pd.DataFrame([[100,100,100],[90,90,90],[86,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# display(df.loc['张三'],type(df.loc['张三']))
display(df['语文'],type(df['语文']))
DataFrame切片、布尔、标签数组索引
- df[切片],对行操作;df[索引],对列操作
- 布尔数组是对行操作
- 标签数组是对列操作
df = pd.DataFrame([[100,100,100],[90,90,90],[86,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# 混合操作,列确定,对行切片
# display(df['语文'].loc['张三':'李四'])
# display(df['语文'].iloc[0:1])
# 混合操作,行确定,对列切片
# display(df.loc['张三'].loc['语文':'数学'])
# display(df.loc['张三'].iloc[0:1])
# 混合操作,对行切片,对列切片
# display(df.loc['张三':'李四'])
# display(df.loc['张三':'李四'].loc['语文':'数学'])
# display(df.loc['张三':'李四','语文':'数学'])
# 仅对行进行切片操作
# display(df.loc['张三':'李四'])
# display(df.iloc[0:1])
# 仅对列进行切片操作
# display(df['语文':'数学'])
display(df.loc[:,'语文':'数学'])
df = pd.DataFrame([[100,100,100],[90,90,90],[86,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# 一维布尔数组,对行进行操作,不是对列进行操作
# bArray=[True,True,False]
# display(df[bArray])
# 二维布尔数组,对DataFrame的每一个元素进行运算,True保留,False值设置为NaN
display(df>85)
display(df[df>85])
df = pd.DataFrame([[100,100,100],[90,90,90],[86,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# 标签数组,对列进行操作
lArray = ['语文','数学']
display(df[lArray])
DataFrame运算
- 转置
- DataFrame之间运算,不但行索引要对齐,列索引也要对齐,否则产生空值。如果不想要空值,可使用DataFrame的函数代替运算符计算,通过参数fill_value参数指定填充值
- DataFrame和Series运算,默认Series索引匹配DataFrame列索引,然后进行广播。当然,我们可以通过axis参数,指定行索引匹配还是列索引匹配
df=pd.DataFrame(np.arange(1,5).reshape(2,2))
display(df,df.T)
# DataFrame对象之间操作,行索引对应,列索引也对齐
# df = pd.DataFrame(np.ones((2,2)))
# df2 = pd.DataFrame(np.ones((2,2)))
# display(df,df2)
# display(df+df2)
# DataFrame对象之间操作,行索引,列索引不对齐
df = pd.DataFrame(np.ones((2,2)))
df2 = pd.DataFrame(np.ones((2,2)),index=[1,2],columns=[1,2])
display(df,df2)
# DataFrame对象之间行和列索引不对齐化,首先补齐行索引和列索引,数据填充NaN,然后再进行操作
display(df+df2)
# 如果不想要运算结果为空值的话,就可以使用函数(add)来替换操作符(+),通过fill_value参数指定填充值
display(df.add(df2,fill_value=10))
# DataFrame和Sereis之间运算
df = pd.DataFrame(np.arange(1,5).reshape(2,2))
s = pd.Series([10,20])
display(df,s)
# 默认Series对象标签和DataFrame的列 标签匹配,广播,再计算
display(df+s)
# 设置Sereis对象标签和DataFrame的行标签匹配,广播,再计算
display(df.add(s,axis='index'))
过程分析图:
![v2-3c40829a650f96ab57be6975d78f8601_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/da0d78202e54212c80e662b89507afee.png)
排序
索引排序
Sereis和DataFrame对象可以使用sort_index对索引进行排序。DataFrame还可以通过axis指定对行还是列索引进行排序,也可以通过ascending参数指定升序还是降序排序
值排序
Sereis和DataFrame对象使用sort_value方法进行值排序
# 索引排序
df = pd.DataFrame(np.arange(9).reshape(3,3),index=[3,1,2],columns=[6,4,5])
display(df)
# 对行索引排序
# display(df.sort_index())
# 对列索引排序
# display(df.sort_index(1))
# inplace,True对原有的数据进行排序,sort_index返回None,False对拷贝得到的数据进行排序
# df.sort_index(inplace=True)
# display(df)
# ascending指定升降序,False降序,True升序
display(df.sort_index(ascending=False))
执行结果:
| | 6 | 4 | 5 | | ---- | ---- | ---- | ---- | | 3 | 0 | 1 | 2 | | 1 | 3 | 4 | 5 | | 2 | 6 | 7 | 8 |
| | 6 | 4 | 5 | | ---- | ---- | ---- | ---- | | 3 | 0 | 1 | 2 | | 2 | 6 | 7 | 8 | | 1 | 3 | 4 | 5 |
# df = pd.DataFrame([[100,100,100],[90,90,90],[86,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
# display(df)
# 对列数据, 比如对外语数据进行从小到大的排序
# df.sort_values('外语',axis=0,inplace=True)
# display(df)
# 对行数据,比如王五成绩按照从小到大排序
# display(df.sort_values('王五',axis=1))
# 对多列数据进行排序,比如对语文和数学进行排序,先对语文排序,语文相等,再根据第二列数学进行排序
df = pd.DataFrame([[100,100,100],[100,90,90],[100,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
display(df.sort_values(['语文','数学'],axis=0))
执行结果:
| | 语文 | 数学 | 外语 | | ---- | ---- | ---- | ---- | | 张三 | 100 | 100 | 100 | | 李四 | 100 | 90 | 90 | | 王五 | 100 | 80 | 80 |
| | 语文 | 数学 | 外语 | | ---- | ---- | ---- | ---- | | 王五 | 100 | 80 | 80 | | 李四 | 100 | 90 | 90 | | 张三 | 100 | 100 | 100 |
索引对象
Series、DataFrame的index或者DataFrame的columns都是是一个索引对象
- 索引对象可以像数组那样进行索引访问
- 索引对象内容是不可修改
df = pd.DataFrame(np.arange(9).reshape(3,3))
display(df)
# index和columns都是索引对象
display(df.index,type(df.index))
display(df.columns,type(df.columns))
index = df.index
display(index[0])
# 不支持修改索引对象中内容
# index[0]=4
# 支持指向一个新的索引对象
index2 = pd.Index([4,5,6])
df.index = index2
display(df)
执行结果:
| | 0 | 1 | 2 | | ---- | ---- | ---- | ---- | | 0 | 0 | 1 | 2 | | 1 | 3 | 4 | 5 | | 2 | 6 | 7 | 8 |
RangeIndex(start=0, stop=3, step=1)
pandas.core.indexes.range.RangeIndex
RangeIndex(start=0, stop=3, step=1)
pandas.core.indexes.range.RangeIndex
0
| | 0 | 1 | 2 | | ---- | ---- | ---- | ---- | | 4 | 0 | 1 | 2 | | 5 | 3 | 4 | 5 | | 6 | 6 | 7 | 8 |
统计相关方法
- mean/sum/count
- max/min
- cumsum/cumprod
- argmax/argmin
- idxmax/idxmin
- var/std
df = pd.DataFrame([[np.nan,np.nan,100],[100,100,90],[86,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# 统计非NaN值的个数,默认按照列来统计,axis=1设置按照行统计
display(df.count())
display(df.count(axis=1))
执行结果:
| | 语文 | 数学 | 外语 | | ---- | ----- | ----- | ---- | | 张三 | NaN | NaN | 100 | | 李四 | 100.0 | 100.0 | 90 | | 王五 | 86.0 | 80.0 | 80 |
语文 2
数学 2
外语 3
dtype: int64
张三 1
李四 3
王五 3
dtype: int64
df = pd.DataFrame([[100,95,100],[95,100,90],[86,80,80]],index=['张三','李四','王五'],columns=['语文','数学','外语'])
display(df)
# idxmax返回数据最大值所对应的索引,默认按照列
# display(df.idxmax())
# # axis=1,设置按照行,找到每行最大值对应的索引
# display(df.idxmax(axis=1))
# idxmin回数据最小值所对应的索引,默认按照列
display(df.idxmin())
# axis=1,设置按照行,找到每行最小值对应的索引
display(df.idxmin(axis=1))
执行结果:
| | 语文 | 数学 | 外语 | | ---- | ---- | ---- | ---- | | 张三 | 100 | 95 | 100 | | 李四 | 95 | 100 | 90 | | 王五 | 86 | 80 | 80 |
语文 王五
数学 王五
外语 王五
dtype: object
张三 数学
李四 外语
王五 数学
dtype: object