文章目录
注:所将可能是python2演示的,而与Python3有区别,要注意。
一、pandas 索引
序列以及二维数组的索引
#np.random.rand(d0,d1,d2……dn)
注:使用方法与np.random.randn()函数相同
作用:
通过本函数可以返回一个或一组服从“0~1”均匀分布的随机样本值。随机样本取值范围是[0,1),不包括1。
应用:在深度学习的Dropout正则化方法中,可以用于生成dropout随机向量(dl),例如(keep_prob表示保留神经元的比例):dl = np.random.rand(al.shape[0],al.shape[1]) < keep_prob
s1=pd.Series(np.random.rand(5),index=['a','b','c','d','e'])
#1查看Series序列索引
print(s1.index)
#2为索引赋一个名字
s1.index.name='alpha'
print(s1)
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
alpha
a 0.334112
b 0.074574
c 0.689593
d 0.448733
e 0.157336
dtype: float64
Process finished with exit code 0
data3=pd.DataFrame(np.random.randn(4,3),columns=['one','two','three'])
print(data3)
#1二维数组获取行索引
print(data3.index)
#2二维数组获取列索引
print(data3.columns)
#3为行列索引起名字
data3.index.name='row'
data3.columns.name='col'
print(data3)
#4pandas中内置了很多索引的类,如RangeIndex,Index这里以python3为例,视频中是Python2,有些区别
#查询pandas中内置的索引类
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
one two three
0 -0.300068 0.107822 -0.461084
1 0.071834 -0.927457 0.323366
2 -0.103444 -0.157807 -2.089129
3 0.752966 -1.488562 0.781543
RangeIndex(start=0, stop=4, step=1)
Index(['one', 'two', 'three'], dtype='object')
col one two three
row
0 -0.300068 0.107822 -0.461084
1 0.071834 -0.927457 0.323366
2 -0.103444 -0.157807 -2.089129
3 0.752966 -1.488562 0.781543
Process finished with exit code 0
重复索引
s1=pd.Series(np.arange(6),index=['a','b','c','b','d','a'])
print(s1)
#1重复索引a有两个值,返回Series
print(s1['a'])
#2未重复索引返回是一个标量数据
print(s1['c'])
#3判断是否有重复索引
print(s1.index.is_unique)#False,即有重复索引
#4返回唯一索引
print(s1.index.unique())
#5对有重复索引的数据进行清洗,与业务有关,有时只需要保留第一个重复索引值,有时要把重复索引值加起来,或求平均
print(s1.groupby(s1.index).sum())#根据索引分组之后求和来聚合,求平均mean()
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
a 0
b 1
c 2
b 3
d 4
a 5
dtype: int32
a 0
a 5
dtype: int32
2
False
Index(['a', 'b', 'c', 'd'], dtype='object')
a 5
b 4
c 2
d 4
dtype: int32
Process finished with exit code 0
多层索引
MultiIndex多层索引类
注:可以将更高维度数据用二维数据表示。行两个索引,列一个索引就表示三维数组,二维数组可读性比高维度高。
例如:股票行索引日期与股票代码,列索引:股票开盘价,收盘价,成交量来表示。
#1创建多级索引
a=[['a','a','a','b','b','c','c'],[1,2,3,1,2,2,3]]
#将列表用zip组装成内层为元组形式。以下两种形式等价
# t=list(zip(*a))#这种形式与a=zip(['a','a','a','b','b','c','c'],[1,2,3,1,2,2,3])
# #结果中就是两个元组中的元素两两依次组合[('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('c', 2), ('c', 3)]
# print(t)#print(list(a))等价
t=list(zip(a))
print(*a)#['a', 'a', 'a', 'b', 'b', 'c', 'c'] [1, 2, 3, 1, 2, 2, 3]解包后发现就是两个列表,在用zip函数进行合并时就是每一个列表中取一个组成元组。
#所以刚才的等价,因为后者a=zip(['a','a','a','b','b','c','c'],[1,2,3,1,2,2,3])就是直接传进两个列表了,所以不需要解包了。
# t=list(zip(a))print(t)#这种没有解包,直接将a=[['a','a','a','b','b','c','c'],[1,2,3,1,2,2,3]]大列表进行合并所以就只有一个列表
#即整体取第一个元素即['a', 'a', 'a', 'b', 'b', 'c', 'c']因为没第二个列表元素,但又要是元组,所以加了个逗号;将列表中第二部分也取出来,变为元组加逗号。
# 所以结果才为[ (['a', 'a', 'a', 'b', 'b', 'c', 'c'],) , ([1, 2, 3, 1, 2, 2, 3],) ]
Series多级索引
#1创建多级索引
a=[['a','a','a','b','b','c','c'],[1,2,3,1,2,2,3]]
#将列表用zip组装成内层为元组形式。以下两种形式等价
# t=list(zip(*a))#这种形式与a=zip(['a','a','a','b','b','c','c'],[1,2,3,1,2,2,3])
# #结果中就是两个元组中的元素两两依次组合[('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('c', 2), ('c', 3)]
# print(t)#print(list(a))等价
t=list(zip(*a))
print(t)#可以用这个数组结果创建多级索引了。
#2创建多级索引,并起名字
inde=pd.MultiIndex.from_tuples(t,names=['level1','level2'])
print(inde)
#3有了多层索引就可以创建Series或DataFrame了,7个索引就有7个数据
s=pd.Series(np.random.rand(7),index=inde)
print(s)
#3选取1级所以为b的所有元素出来
print(s['b'])
#4选取1级所以为b与c的所有元素出来
print(s['b':'c'])
#5用列表选取1级所以为a与c的所有元素出来
print(s[['a','c']])
#6 1级索引任意,2级索引为2的出来
print(s[:,2])
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
[('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('c', 2), ('c', 3)]
MultiIndex(levels=[['a', 'b', 'c'], [1, 2, 3]],
codes=[[0, 0, 0, 1, 1, 2, 2], [0, 1, 2, 0, 1, 1, 2]],
names=['level1', 'level2'])
level1 level2
a 1 0.567812
2 0.936409
3 0.194581
b 1 0.090835
2 0.490026
c 2 0.877824
3 0.796039
dtype: float64
level2
1 0.090835
2 0.490026
dtype: float64
level1 level2
b 1 0.090835
2 0.490026
c 2 0.877824
3 0.796039
dtype: float64
level1 level2
a 1 0.567812
2 0.936409
3 0.194581
c 2 0.877824
3 0.796039
dtype: float64
level1
a 0.936409
b 0.490026
c 0.877824
dtype: float64
Process finished with exit code 0
DataFrame多级索引
#1直接创建DataFrame的多级索引,行列索引各两层,并为行列的每层索引命名
#index=[['a','a','b','b'],[1,2,1,2]]这种就是列表套列表的,即2层索引就是内层第一个列表为一个索引,内层第二个列表也是一个索引
da1 = pd.DataFrame(np.random.randint(1,10,(4,3)), index=[['a','a','b','b'],[1,2,1,2]],
columns=[['one','one','two'],['blue','red','blue']])
# 2并为行列的每层索引命名
da1.index.names=['row-1','row-2']
da1.columns.names=['col-1','col-2']
print(da1)
#3选取1级行索引a,其实也是一个DataFrame
print(type(da1.loc['a']))#<class 'pandas.core.frame.DataFrame'>#
# pandas.core.frame.DataFrame 就代表了我们这里DataFrame来自frame模块,而frame模块是属于core模块的,同时pandas包又是由core模块等组成。
# Pandas有两个主要的数据结构:Series和DataFrame都是这样的
#Pandas 的数据结构 DataFrame 即数据集的常用方法
print(da1.loc['a'])
#4选取1级索引为a,2级索引为1的,就是一个二级索引的序列
print(da1.loc['a',1 ])
print(da1.loc['a',1 ].index)
#二级索引,codes=[[0, 0, 1], [0, 1, 0]],就是1级索引one为0 two为1;2级索引blue为0,red为1;
# 在[['one','one','two'],['blue','red','blue']]中的位置所以就是[[0, 0, 1], [0, 1, 0]]了
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
col-1 one two
col-2 blue red blue
row-1 row-2
a 1 9 6 4
2 1 8 3
b 1 1 2 3
2 4 6 3
<class 'pandas.core.frame.DataFrame'>
col-1 one two
col-2 blue red blue
row-2
1 9 6 4
2 1 8 3
col-1 col-2
one blue 9
red 6
two blue 4
Name: (a, 1), dtype: int32
MultiIndex(levels=[['one', 'two'], ['blue', 'red']],
codes=[[0, 0, 1], [0, 1, 0]],
names=['col-1', 'col-2'])
索引的交换
#1直接创建DataFrame的多级索引,行列索引各两层,并为行列的每层索引命名
#index=[['a','a','b','b'],[1,2,1,2]]这种就是列表套列表的,即2层索引就是内层第一个列表为一个索引,内层第二个列表也是一个索引
da1 = pd.DataFrame(np.random.randint(1,10,(4,3)), index=[['a','a','b','b'],[1,2,1,2]],
columns=[['one','one','two'],['blue','red','blue']])
# 2并为行列的每层索引命名
da1.index.names=['row-1','row-2']
da1.columns.names=['col-1','col-2']
print(da1)
#3将行索引的两个交换,原来da1不变
da2=da1.swaplevel('row-1','row-2')
print(da1)
print(da2)
#4对交换后的索引即da2按照1级索引进行排序,所以为0即1级索引
# da2.sort_level(0)
# print(da2)
#5多级索引下进行统计
#根据1级索引求和即0,即1级索引以后的值都加起来,或根据二级索引求和即(level=1)
print(da1.sum(level=0))
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
col-1 one two
col-2 blue red blue
row-1 row-2
a 1 1 7 5
2 9 9 7
b 1 4 8 2
2 6 8 3
col-1 one two
col-2 blue red blue
row-1 row-2
a 1 1 7 5
2 9 9 7
b 1 4 8 2
2 6 8 3
col-1 one two
col-2 blue red blue
row-2 row-1
1 a 1 7 5
2 a 9 9 7
1 b 4 8 2
2 b 6 8 3
col-1 one two
col-2 blue red blue
row-1
a 10 16 12
b 10 16 5
Process finished with exit code 0
文件读取创建多级索引
#一般我们会从文件中读取DataFrame出来,将里面有些列设置成索引,这样来构成多级索引的DataFrame,而不是一个一个索引写麻烦。
#字典直接将键作为列索引了,行默认索引;
#1如从文件中读取出来假如为下边的这个DataFrame
df1=pd.DataFrame({
'a':range(7),
'b':range(7,0,-1),
'c':['one','one','one','two','two','two','two'],
'd':[0,1,2,0,1,2,3]})
print(df1)
#2将某些列设置成索引值
print(df1.set_index('c'))
#3将c与d都作为索引生成2级索引
df2=df1.set_index(['c','d'])
print(df1.set_index(['c','d']))
#4将二级索引的df2再变回去为原来的df1形式,只不过a b c d 顺序有变化,其他一样
df3=df2.reset_index()
print(df3)
#4将df3根据列索引排序就真正回到df1了。
print(df3.sort_index('columns'))
print(df2.reset_index().sort_index('columns')==df1)
#发现都是true所以说明df2.reset_index().sort_index('columns')与df1一样了。
#上面的df3我们分两步进行,也可以一步转到df1如:df2.reset_index().sort_index('columns')
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
a b c d
0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
3 3 4 two 0
4 4 3 two 1
5 5 2 two 2
6 6 1 two 3
a b d
c
one 0 7 0
one 1 6 1
one 2 5 2
two 3 4 0
two 4 3 1
two 5 2 2
two 6 1 3
a b
c d
one 0 0 7
1 1 6
2 2 5
two 0 3 4
1 4 3
2 5 2
3 6 1
c d a b
0 one 0 0 7
1 one 1 1 6
2 one 2 2 5
3 two 0 3 4
4 two 1 4 3
5 two 2 5 2
6 two 3 6 1
a b c d
0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
3 3 4 two 0
4 4 3 two 1
5 5 2 two 2
6 6 1 two 3
a b c d
0 True True True True
1 True True True True
2 True True True True
3 True True True True
4 True True True True
5 True True True True
6 True True True True
Process finished with exit code 0
二、pandas 分组运算
总图:
分组原理:
第一部分分组
df1=pd.DataFrame({
'key1':['a','a','b','b','a',],
'key2':['one','two','one','two','one'],
'data1':np.random.randint(1,10,5),
'data2':np.random.randint(1,10,5)})
print(df1)
print(df1['data1'])
df3=df1['data1'].groupby(df1['key1'])
print(df3)#<pandas.core.groupby.generic.SeriesGroupBy object at 0x000002531D8D1C50>#是一个分组对象了。
#1取出'data1'这一列并根据key1为键进行分组,用求平均聚合,用不重复的key1为索引输出结果即可。
df2=df1['data1'].groupby(df1['key1']).mean()
print(df2)
#2分组的键索引不一定必须是df1中的某一列,也可以定义
key=[1,2,1,1,2]
df4=df1['data1'].groupby(key).mean()
print(df4)
#3将data1这一列数据生成有多层索引的Series序列,即先根据key1分组,之后分完后再根据key2分组
df5=df1['data1'].groupby([df1['key1'],df1['key2']]).mean()
print(df5)
#4看上一步分组后的个数
print(df1['data1'].groupby([df1['key1'],df1['key2']]).size())
#5直接对整个数组df1分组,,因为key2不是数字,所以分组计算时就把他扔掉了。
df6=df1.groupby('key1').sum()
print(df6)
#6 df6又是数组,所以可以只看data1结果
df7=df1.groupby('key1').sum()['data1']
print(df7)
#7对整个数组指定多层索引进行分组,之后取data1数据
df8=df1.groupby(['key1','key2']).sum()['data1']
print(df8)
#8将df8转化为datafram格式,即行与列索引
df9=df8.unstack()
print(df9)
#9pandas分组groupby支持python的迭代器协议的,所以直接可以用for迭代
for name ,group in df1.groupby('key1'):#每次迭代返回分组的名字与对应数据
print(name)
print(group)
#10groupby支持python的迭代器协议的,也可以直接转化为列表或字典
#a=list(df1.groupby('key1'))#结果是列表中套的元组作为元素
#print(a)
#b=dict(list(df1.groupby('key1')))
#print(b)#转化为字典了。
a=dict(list(df1.groupby('key1')))
print(a)
print(a['a'])#获取键a对应大的数据
#11以上都是按照axis=0方向分组的,也可以按照列axis=1的方向进行分组
#看一下各列数据类型
print(df1.dtypes)#df1.dtypes就是序列即<class 'pandas.core.series.Series'>
print(df1.dtypes.value_counts())
print(type(df1.dtypes))
#12 按照列方向分组,即按照df1.dtypes的序列值int32与object进行分成2组即可,发现求和时对应字符串连接起来了。
df10=df1.groupby(df1.dtypes,axis=1).sum()
print(df10)
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
key1 key2 data1 data2
0 a one 8 4
1 a two 2 6
2 b one 3 5
3 b two 5 1
4 a one 9 1
0 8
1 2
2 3
3 5
4 9
Name: data1, dtype: int32
<pandas.core.groupby.generic.SeriesGroupBy object at 0x000001B971F1AFD0>
key1
a 6.333333
b 4.000000
Name: data1, dtype: float64
1 5.333333
2 5.500000
Name: data1, dtype: float64
key1 key2
a one 8.5
two 2.0
b one 3.0
two 5.0
Name: data1, dtype: float64
key1 key2
a one 2
two 1
b one 1
two 1
Name: data1, dtype: int64
data1 data2
key1
a 19 11
b 8 6
key1
a 19
b 8
Name: data1, dtype: int32
key1 key2
a one 17
two 2
b one 3
two 5
Name: data1, dtype: int32
key2 one two
key1
a 17 2
b 3 5
a
key1 key2 data1 data2
0 a one 8 4
1 a two 2 6
4 a one 9 1
b
key1 key2 data1 data2
2 b one 3 5
3 b two 5 1
{
'a': key1 key2 data1 data2
0 a one 8 4
1 a two 2 6
4 a one 9 1, 'b': key1 key2 data1 data2
2 b one 3 5
3 b two 5 1}
key1 key2 data1 data2
0 a one 8 4
1 a two 2 6
4 a one 9 1
key1 object
key2 object
data1 int32
data2 int32
dtype: object
int32 2
object 2
dtype: int64
<class 'pandas.core.series.Series'>
int32 object
0 12 aone
1 8 atwo
2 8 bone
3 6 btwo
4 10 aone
Process finished with exit code 0
通过字典进行分组
df1=pd.DataFrame(np.random.randint(1,10,(5,5)),
columns=['a','b','c','d','e'],
index=['Alice','Bob','Candy','Dark','Emily'])
#将两个元素变为NaN,在Python中用iloc与loc,不要用python2中的ix会警告
# df1.ix[1,1:3]=np.NaN
df1.loc['Bob','b':'c']=np.NaN
print(df1)
#1说明非数字在分组中的情况处理,创建一个字典作为分组的key,将a这一列名称映射到red,其他依次映射
mapp={
'a':'red','b':'red','c':'blue','d':'orange','e':'blue'}
#2分组时,df1按照字典映射关系进行分组
grou=df1.groupby(mapp,axis=1)#因为映射关系根据列名称来的,所以写成列按照列来分组
#对分好的组进行求和,发现NaN作为0处理了。
df2=grou.sum()
print(df2)
#3查看分组后的各个数量,blue为2列
print(grou.size())
#4查看对于每一个分组后,如blue对应的行标签Alice 的数目为2,其他类似。且NaN不计入数目
print(grou.count())
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
a b c d e
Alice 2 4.0 4.0 7 8
Bob 5 NaN NaN 9 9
Candy 7 2.0 1.0 8 2
Dark 9 3.0 5.0 4 1
Emily 5 5.0 6.0 4 4
blue orange red
Alice 12.0 7.0 6.0
Bob 9.0 9.0 5.0
Candy 3.0 8.0 9.0
Dark 6.0 4.0 12.0
Emily 10.0 4.0 10.0
blue 2
orange 1
red 2
dtype: int64
blue orange red
Alice 2 1 2
Bob 1 1 1
Candy 2 1 2
Dark 2 1 2
Emily 2 1 2
Process finished with exit code 0
通过函数进行分组
df1=pd.DataFrame(np.random.randint(1,10,(5,5)),
columns=['a','b','c','d','e'],
index=['Alice','Bob','Candy','Dark','Emily'])
print(df1)
#1通过函数分组,函数参数为分组时候要计算的索引名字,就是根据函数返回值进行分组的。
# def groupky(idx):
# print(idx)#通过打印每一次的分组标签,可以看到默认是按照行进行分组的。所以这句话将每一行索引打出来
# return idx
# df2=df1.groupby(groupky)
# print(df2)
# print(df2.size())#按照行分组,所以行索引没有重复的,所以每一个分组都只有一组数据。
# #2
# def groupky(idx):
# print(idx)#通过打印每一次的分组标签,可以看到默认是按照行进行分组的。所以这句话将每一行索引打出来
# return len(idx)#分组返回按照字母的长度分组,如Bob有三个字符即3为一组:
# # 数量有1个;Candy,Alice,Emily有5个字符,所以5个字符的分组数目为3个。
# df2=df1.groupby(groupky)
# print(df2)
# print(df2.size())#按照行分组,所以行索引没有重复的,所以每一个分组都只有一组数据。
#3 上面2的按照行标签的字符个数分组方式,效果一样,其最简单的写法为:因为len就是函数,且默认又是按照行索引分组
df2=df1.groupby(len).size()
print(df2)
print(df1.groupby(len).sum())#因为字符个数为5的有三个数目,对应相加,其他2个组就一组,所以不动
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
a b c d e
Alice 9 9 7 8 9
Bob 2 3 7 6 8
Candy 8 3 4 3 9
Dark 4 8 6 5 3
Emily 4 8 2 1 9
3 1
4 1
5 3
dtype: int64
a b c d e
3 2 3 7 6 8
4 4 8 6 5 3
5 21 20 13 12 27
Process finished with exit code 0
多级索引分组情况
#1创建一个多级索引,列索引两层,行索引默认
colunm=pd.MultiIndex.from_arrays([['China','USA','China','USA','China'],
['A','A','B','C','B']],names=['country','index'])
#注意这里不用from_tuples因为1内层不是元组形式
# 2因为用两个索引,所以列表的内层必须是元组形式,即[('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('c', 2), ('c', 3)]
# 且每个元组中个数必须保证是2个如('a', 1),而内层元组个数可以多个。('a', 1)、('a', 3),这多个元组
#因为不满足元组条件所以用的是数组创建的多层索引from_arrays,列表中的各个小列表作为一个索引
#2查看多级索引
print(colunm)
df1=pd.DataFrame(np.random.randint(1,10,(5,5)),
columns=colunm)
print(df1)
#3多级索引分组时,可以根据索引级别进行分组。
df2=df1.groupby(level='country',axis=1)#根据country分组是列索引,所以必须指定按照列分组,因为默认行索引没这个。
print(df2)
print(df2.sum())
#4按照index分组
df3=df1.groupby(level='index',axis=1)#根据index分组是列索引,所以必须指定按照列分组,因为默认行索引没这个。
print(df3)
print(df3.sum())
结果:
D:\ProgramData\Anaconda3\python.exe D:/numpy-kexue/03.py
MultiIndex(levels=[['China', 'USA'], ['A', 'B', 'C']],
codes=[[0, 1, 0, 1, 0], [0, 0, 1, 2, 1]],
names=['country', 'index'])
country China USA China USA China
index A A B C B
0 9 4 8 6 4
1 2 4 9 6 9
2 7 7 6 1 1
3 6 6 8 4 9
4 4 7 5 8 8
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001EB8F7D3D30>
country China USA
0 21 10
1 20 10
2 14 8
3 23 10
4 17 15
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001EB8E0D0978>
index A B C
0 13 12 6
1 6 18 6
2 14 7 1
3 12 17 4
4 11 13 8
Process finished with exit code 0
三、聚合运算
注:分组完后的数据进行计算即为聚合
内置聚合函数
df1=pd.DataFrame({
'key1':['a','a','b','b','a',],
'key2':['one','two','one','two','one'],
'data1':np.random.randint(1,10,5),
'data2':np.random.randint(1,10,5)})
print(df1)
#1内置求和函数聚合,以及平均值mean,最小值min,最大值max,以及describe就是会对每个分组用一系列的内置函数进行聚合
print(df1.groupby('key1').sum())
自定义聚合函数
df1=pd.DataFrame({
'key1':['a','a','b','b','a',],
'key2':['one','two','one','two','one'],
'data1':np.random.randint(1,10,5),
'data2':np.random.randint(1,10,5)})
print(df1)
df2=df1.groupby('key1')
#1自定义一个聚合函数最大值减去最小值
def man(s):
print(type(s))#聚合函数中的参数s就是逐个索引对应的记录。类型就是series,即每次
# print(s)#类型就是series,即每次都是返回一个分组的对应数据
return s.max()-s.min()