数据分析步骤
概念:数据分析是用适当的统计方法对收集的大量数据进行分析,提取有用的信息,对数据加以分析和概括的过程
数据分析师需要具备的能力
数理知识(数学能力)
数据获取加工能力
行业知识
1明确目的思路
2数据收集
3数据处理
4数据分析
5数据展现
数据加载 read_csv
read_csvz方法读取文件,返回的是DataFrame对象,默认将第一行作为DataFrame的列标签
设置header=None,csv文件第一行就不会作为列标签
sep/delimiter 可以通过这两个参数设置分隔符的样式
names参数可以可以设置列索引
index_col参数可以设置行索引
df=pd.read_csv(‘data.csv’,header=None,index_col=0)
输出的结果,就会把第一列作为行索引
usecols参数可以获得读取的文件中我们所需要的数据
df=pd.read_csv(‘data.csv’,usecols=[1,2])
输出结果只显示第一列和第二列的数据
从数据库中获取数据
import pymysql
con=pymysql.connect(‘localhost’,‘root’,‘123456’,‘要读取的数据库名’)
df=pd.read_sql(‘select * from 表名’,con)
display(df.head())
写入csv文件to_csv
index:是否写入行索引,默认是True
index_lable:索引字段的名称
header:是否写入列索引,默认是True
na_rep:空值表示
columns:写入的字段,默认是全部写入
sep:分隔符
创建df对象
df=pd.DataFrame(np.array(1,10).reshape(3,3))
将df对象写入csv
df.to_csv(‘data.csv’)
可以通过index参数来设置是否写入行索引,默认情况下index=True,当index=False时,写入的文件没有行索引的标签
可以通过header参数来设置列索引的写入,header=True表示的是写入,header=False表示的不写入
空值默认 写入到文件中不显示,na_rep指定空值在文件中的显示效果
df.to_csv(‘data.csv’,header=False,na_rep=‘空’)
在文件中,空值的显示效果是’空’
columns参数可以设置DataFrame对象的哪些列可以写入到文件中,默认是写入所有列
df.to_csv(‘data.csv’,header=False,columns=[1,2])表示的是只把第一第二列写入到文件中
数据清洗
概念:收集到的数据无法保证数据一定准确,有效的,需要进行清洗,包括一下步骤
1处理缺失值
2处理异常值
3处理重复值
发现缺失值
info:检查缺失值使用info对整体数据进行查看,显示DataFrame对象的每列信息
display(df.info())
isnull:display(df.isnull())也会显示DataFrame的缺失值,会把所有的数据以true和false的形式,也可单独的显示某一列的数据display(df[10].isnull())表示的是只显示第10列所有的信息,单一的isnull方法在查找缺失值时候很麻烦,结合any方法display(df[10].isnull().any())
如果返回的是True,说明存在至少一个缺失值
notnull:和isnull方法一样
丢弃缺失值
对于缺失值可以通过dropna方法进行丢弃处理,如果不传入任何参数,只要存在缺失值就会默认删除整行数据display(df.dropna()),有以下参数
how:指定dropna丢弃缺失值行为,默认是any
axis:指定丢弃行还是列,默认是丢弃行
thresh:当非空数值达到该值时,保留数据,否则删除
inplace:在指定是否默认修改啊,默认是False
填充缺失值
对于缺失值可以用filna方法进行填充display(df.fillna(1000))表示的是对于缺失值用1000来填充,有以下参数
value:填充所用的值,可以是 一个字典,这样为DataFrame不同列指定不同填充值dislpay(df.fillna({5:100,10:1000}))表示的第五列的缺失值用100填充,第十列的缺失值用1000填充
method:指定上一个有效值填充(pad/fill),还是下一个有效值填充(backfill/bfill)
limit:如果指定method,表示最大NaN的填充数量,如果没有指定method,表示中最大的NaN填充数量
inplace:指定是否就地修改,默认是False
无效值处理
检测无效值:用DataFrame中的describe方法查看数据统计,不同类型统计信息不同基于统计信息,结合业务来检查无效值display(df.describe())会返回数据中的统计,均值,方差,标准差,最大值和最小值
重复值处理
发现重复值:用duplicated方法发现重复值,该放大法返回Series对象,值为布尔类型,表示是否于上一行重复,一般结合any方法整个数据是否重复的数据display(df.duplicated().any()) 有以下参数
subset:可以指定自定义重复规则,默认是所有数据重复才算重复,可有指定设置列
display(df.duplicated(subset=[0,1]))表示的是只要第一列和第二列里面有重复的数据就算是重复数据
keep:display(df.duplicated(keep=‘first’))表示的是后面的数据标记为True
display(df.duplicated(keep=‘last’))表示的前面的数据标记为True
display(df.duplicated(keep=False))表示的是所有重复数据都标记为True,不重复的数据为Fslse
数据过滤
使用布尔数组或者索引数组来过滤数据,另外引入可以使用DataFrame的query方法了来进行数据过滤,如果query方法中使用外面定义的变量需要在变量上加上@
给定一个条件,根据条件生成布尔数组
将得到的布尔数组传回给DataFrame对象进行过滤
语法:
display(df[df[‘a’]==1])表示的是在a列里面,只显示数据是1的数据
如果有多个条件
语法:用小括号括起来每个条件然后用&连接再赋给一个变量,最后输出这个变量
f=(df[‘a’]==1)&(df[‘b’]==1)
display(f)
数据转接
应用与映射
Series和DataFrame都有对元素的映射转换操作,DataFrame作为二位数据具有行和列对应转换操作,对于Serise,可以调用apply或者map方法,对于DataFrame可以调用apply和applymap方法
apply:传入函数实现映射转化,函数参数,Serise传递参数,DataFrame传递行和列对象
map:对当前Serise的值进行映射转换,参数可以是Serise,字典或者函数
applymap:传入函数实现元素的映射转换
元素替换
replace函数
df=df.replace(‘a’,‘b’)把a换成b
对单一的值进行替换
df=df[‘a’].replace(‘c’,‘d’)把a列的c换成d
支持列表多个值,每个替换不同的值,列表执行对应位置转换
s=df[‘a’].replace([‘c’,‘d’],[‘e’,‘f’])把a列中的c和d转换成e和f
replace支持字典方式
s=df[‘a’].replace({‘c’:‘d’,‘e’:‘f’})把a列中的c和d转换成e和f
replace可以是用map或者applymap来实现
def m(item):
if item==‘a’
return b
return item
s=df[a].map(m)
display(s.head())
通过自定义一个方法来实现替换
数据转换 子字符串向量操作
Series含有syr属性通过str能对字符串进行想量级运算从而对数据进行转换
s=pd.Serise([‘a’,‘b’,‘c’])
display(s.str)
display(s.str.upper())把 a b c转换成大写A B C
display(s.str.contains(‘b’))输出包含b的布尔类型
输出结结果:
0 Falase
1 True
2 False
对数据进行过滤
ba=df[a].str.endwith(‘CA’)
display(ba) 过滤出a列中以CA结尾的数据
对数据进行切分
display(df[‘a’].str.split(’,’))对a列数据以‘ , ’分割
数据合并
concat:display(pd.concat((df1,df2)))进行cancat连接的时候,根据索引(默认索引)对齐合并,如果不对齐,产生空值,
有以下参数
df1=pd.DataFrame(np.arange(9).reshape(3,3))
df1=pd.DataFrame(np.arange(10,19).reshape(3,3))
输出结果分别是
0 1 2
0 1 2 3
1 4 5 6
2 7 8 9
0 1 2
0 11 12 13
1 14 15 16
2 17 18 19
axis:指定连接轴(默认是0)axis=0垂直方向,axis=1水平方向
concat:display(pd.concat((df1,df2),axis=1))
0 1 2 0 1 2
0 1 2 3 11 12 13
1 4 5 6 14 15 16
2 7 8 9 17 18 19
join:指定连接方式,默认是外连接参数,参数值outer:并集,inner:交集
concat:display(pd.concat((df1,df2),jion=‘inner’)) 输出结果只显示公共内容:
1 2
0 2 3
1 5 6
2 8 9
如果join=outer则显示全部数据,没有值默认是Nan
keys:用来区分不同的数据组(来源)
display(pd.concat((df1,df2),keys=[‘df1’,df2]))
输出的结果和join=outer一样,只是前面多了df1和df2的行索引
join_axes:指定连接结果集中保留的索引
df1=pd.DataFrame(np.arange(9).reshape(3,3))
df1=pd.DataFrame(np.arange(10,19).reshape(3,3),columns=[1,2,3])
display(pd.concat((df1,df2),join_axes=[df1.columns]))输出结果
0 1 2
0 1.0 2 3
1 4.0 5 6
2 7.0 8 9
0 NaN 10 11
1 NaN 13 14
2 NaN 16 17
ignore_index:忽略原来索引,创建新的整数序列索引,默认为False
0 1 2 3
0 1.0 2 3 NaN
1 4.0 5 6 NaN
2 7.0 8 9 NaN
3 NaN 10 11 12.0
4 NaN 13 14 15.0
5 NaN 16 17 18.0
merge
数据库内连接步骤:1数据组合,2根据等值条件显示
DataFrame merge连接步骤:1数据组合,2根据等值显示
列名都相同,且列值也想相同
join连接
join连接方式和merge一样,数据组合,根据等值显示
join和merge的区别:
创建多级索引
创建方式
第一种:我们在创建Series或者DataFrame的时候,通过index(columns)参数传递多维数组,进而创建多级索引,多级索引可以通过names属性设置名称,每级索引的元素个数相同
第二种:我们通过Multiindex方法创建Multiindex对象,然后作为Series和DataFrame的index(columns)参数值,同样可以通过names参数值指定多层索引的名称
import pandas as pd
import numpy as np
from IPython.core.display import display
##创建单层索引
s=pd.Series([1,1,3,4],index=[[‘湖南’,‘湖南’,‘北京’,‘北京’],[‘长沙’,‘衡阳’,‘海淀’,‘昌平’]])
display(s)
##多层索引,为每一层索引指定名称
s.index,names=[‘省份’,‘城市’]
##输出结果
省份 城市
湖南 长沙 1
衡阳 1
北京 海淀 3
昌平 4
from_arrays:接收一多维数组,高维指定高层索引,低维指定低层索引
##Series创建多级索引通过创建Multiindex对象,试纸给index参数
##from_arrays,通过穿件了列表的方式创建[[第一级索引],[第二集索引],…[第n级索引]]
m=pd.MultiIndex.from_arrays([[‘湖南’,‘湖南’,‘北京’,‘北京’],[‘长沙’,‘衡阳’,‘海淀’,‘昌平’]])
n=pd.Series([1,2,3,4],index=m)
display(n)
输出结果
湖南 长沙 1
衡阳 2
北京 海淀 3
昌平 4
from_tuples:接收一个元素作为列表,每个元组在指定每个索引(高维索引,低维索引)
##from_tuples通过元组构成列表[(第一级元素,第二集元素),(第一级元素索引,第二级元素索引)]
a=pd.MultiIndex.from_tuples([(‘湖南’,‘长沙’),(‘湖南’,‘长沙’),(‘北京’,‘海淀’),(‘北京’,‘昌平’)])
b=pd.Series([1,2,3,4],index=a)
display(b)
输出结果:
湖南 长沙 1
长沙 2
北京 海淀 3
昌平 4
from_product:接收一个可迭代对象列表,根据可迭代对象列表中的元素的笛卡尔积创建多级索引
##from_prodect通过笛卡尔积方式创建Multiindex对象设置给index参数
m=pd.MultiIndex.from_product([[‘湖南’,‘北京’],[‘长沙’,‘衡阳’,‘海淀’,‘昌平’]])
s=pd.Series(np.arange(1,9),index=m)
display(s)
输出结果:
湖南 长沙 1
衡阳 2
海淀 3
昌平 4
北京 长沙 5
衡阳 6
昌平 8
DataFrame创建行级索引*
它和Series多级索引创建没什么区别,方式一:index参数多维数组,方式二:通过MultiIndex类的方法(from_arrays from_tuples from_product)创建MultiIndex对象,设置index
df=pd.DtaFrame(np.arange(1,9).reshape(4,2),index=[[‘湖南’,‘湖南’,‘北京’,‘北京’],[‘长沙’,‘衡阳’,‘海淀’,‘昌平’]])
###from_arrays
m=pd.MultiIndex.from_arrays([[‘湖南’,‘湖南’,‘北京’,‘北京’],[‘长沙’,‘衡阳’,‘海淀’,‘昌平’]])
df=pd.DataFrame(np.arange(1,9).reshape(4,2),index=m)
display(df)
##from_tuples
m=pd.MultiIndex.from_tuples([(‘湖南’,‘长沙’),(‘湖南’,‘长沙’),(‘北京’,‘海淀’),(‘北京’,‘昌平’)])
df=pd.DataFrame(np.arange(1,9).reshape(4,2),index=m)
display(df)
##from_product
m=pd.MultiIndex.from_product([[‘湖南’,‘长沙’],[‘长沙’,‘衡阳’,‘海淀’,‘昌平’]])
df=pd.DataFrame(np.arange(1,17).reshape(8,2),index=m)
display(df)
输出结果:
0 1
湖南 长沙 1 2
衡阳 3 4
海淀 5 6
昌平 7 8
长沙 长沙 9 10
衡阳 11 12
海淀 13 14
昌平 15 16
DtaFrame列多级索引
DataFrame创建列多层索引和行创建多层索引类似,区别在于DataFrame设置给参数columns
df=pd.DtataFrame(np.array([[1,1,1,1],[2,1,2,1]]),index=[‘七里香’,‘双节棍’],columns=[[‘中文’,‘中文’,‘english’,‘english’],[‘喜欢’,‘不喜欢’,‘like’,‘dislike’]])
display(df)
输出结果:
中文 english
喜欢 不喜欢 like dislike
七里香 1 1 1 1
双节棍 2 1 2 1
Serises多层索引
多层索引同样支持单层索引的相关操作,列如索引元素,切片,索引数组原则元素等,我们也可以根据多级索引,按照层次逐级选择元素,多层元素优势 通过高层次索引,来操作整个索引数组的数据 操作语法:
s[操作]
s.loc[操作]
s.iloc[操作]
操作可以是索引,切片,数组索引
Series多层索引
loc:标签索引操作,通过多层索引操作获取该索引对应的一组值
s=pd.Series([1,2,3,4],index=[[‘北京’,‘北京’,‘湖南’,‘湖南’],[‘海淀’,‘昌平’,‘长沙’,‘衡阳’]])
display(s)
##直接使用外层索引,不支持内层索引访问,先从外层索引找,因为外层索引没有‘长沙’,所以会报错
display(s.loc[‘湖南’])
输出结果:
北京 海淀 1
昌平 2
湖南 长沙 3
衡阳 4
dtype: int64
长沙 3
衡阳 4
##外层加内层索引逐层访问
display(s.loc[‘湖南’,‘长沙’])
输出结果:
dtype: int64
3
iloc:位置索引操作获取对应位置的元素值 与是否多层索引无关
display(s.iloc[0])
输出结果:
1
切片操作
##切片操作,根据标签切片,注意:切片操作需要先排好序列(字典顺序)
s=s.sort_index()
display(s.loc[‘北京’:‘湖南’])
输出结果:
北京 昌平 2
海淀 1
湖南 衡阳 4
长沙 3
##根据位置切片
##根据位置切片
s=s.sort_index()
display(s.iloc[0:1])
输出结果:
北京 昌平 2
DataFrame多层索引
loc:标签索引操作,通过多层索引,获取该索引对应的一组值
s= pd.MultiIndex.from_product([[‘湖南’,‘北京’],[‘2017’,‘2018’]])
df=pd.DataFrame(np.array([[800],[8100],[1200],[1150]]),index=s)
##使用外层索引访问,同样不支持直接从内层开始访问
print(df.loc[‘湖南’])
输出结果:
0
2017 800
2018 8100
##通过外层加内层逐渐层访问,得到一行数据
display(df.loc[‘湖南’,‘2017’])
输出结果:
0 8000
iloc:位置索引,获取对应位置的一行数据,与是否多层索引无关
display(df.iloc[0])
输出结果:
Name: (湖南, 2017), dtype: int32
切片操作
##切片操作
df=df.sort_index()
print(df.loc[‘北京’:‘湖南’])
输出结果:
0
北京 2017 1200
2018 1150
湖南 2017 800
2018 8100
##混合操作 要设置axis=0
df = df.sort_index()
display(df.loc(axis=0)[:,‘2017’])注意:loc后面必须要加loc(axis=0)不然系统不知道我们指定的是行,如果是Series就可以不用加,因为Series是一维数据
位置切片
##位置切片
print(df.iloc[0:1])
输出结果:
0
北京 2017 1200
索引交换
我们可以通过调用DataFame对象的swaplevel方法交换两个层级索引,该方法默认对倒数第二层和倒数第一层进行交换。我们可以指定交换的层级,层次从0开始,由外向内递增,也可以指定负值负值表示倒数第n层,我们可以通过层级索引的名称进行交换。
m=pd.MultiIndex.from_arrays([[‘湖南’,‘湖南’,‘北京’,‘北京’],[‘东部’,‘西部’,‘东部’,‘西部’]])
df=pd.DataFrame(np.arange(1,9).reshape(4,2),index=m)
display(df.swaplevel())
输出结果:
0 1
东部 湖南 1 2
西部 湖南 3 4
东部 北京 5 6
西部 北京 7 8
我们还可以自定义交换的层数,层级是从外向内一次是第0层,第一层,第n层
display(df.swaplevel(0,2))
表示的将第0层和第2层的索引进行交换
也可以根据列名交换,首先得设置列名
df.index.names=[‘a’,‘b’,‘c’]
display(df.swaplevel(‘a’,‘c’))
表示也是把第0层和第2层交换索引
索引排序
我们可以用sort_index的方法对索引进行排序
level:指定根据哪一层进行排序,默认是最外层,level可以是数值,索引名或者是二者构成的列表
inplace:是否就地修改,默认是False
索引的堆叠
通过DataFrame对象的stack的方法可以进行索引的堆叠,即,将指定层级的列转换成行
level:level参数指定转换的层级,默认是-1
通过DataFrame的unstack的方法可以取消索引的堆叠,即,将指定的层级转换成列
level参数指定转换的层级,默认是-1
fill_value参数指定填充值,默认是NaN
取消堆叠操作,可能会产生NaN,避免空值,填充数据使用fill_value
df=pd.DataFrame(np.arange(1,9).reshape(4,2),index=[[‘B’,‘A’,‘B’,‘A’],[‘a1’,‘a1’,‘b1’,‘c1’],[‘a2’,‘b2’,‘b2’,‘c2’]])
df=df.unstack(fill_value=0)
print(df)
输出结果:
0 1
a2 b2 c2 a2 b2 c2
A a1 0 3 0 0 4 0
c1 0 0 7 0 0 8
B a1 1 0 0 2 0 0
b1 0 5 0 0 6 0
如过不指定要转换的列,默认是从最里面的开始,也可以通过lecel指定要转换的列
df=df.unstack(level=0,fill_value=0)
print(df)
将行索引堆叠到列上面
df=pd.DataFrame(np.array([[‘1’,‘1’,‘1’,‘1’],[‘2’,‘1’,‘2’,‘1’]]),index=[‘七里香’,‘双节棍’],columns=[[‘中文’,‘中文’,‘english’,‘english’],[‘喜欢’,‘不喜欢’,‘like’,‘dislike’]])
##获取七里香的中文信息,在列索引上,0表示最外层的索引
df=df.stack(0)
print(df)
输出结果:
dislike like 不喜欢 喜欢
七里香 english 1 1 NaN NaN
中文 NaN NaN 1 1
双节棍 english 1 2 NaN NaN
中文 NaN NaN 1 2
索引的设置
在DataFrame中我们需要你将现有的某一列或者多列进行索引, 可以调用set_index方法实现,参数如下
droyop:是否丢弃作为新索引列,默认为True
append:是否以追加方式设置索引,默认为False
inplace:是否就地修改,默认为False
df=pd.DataFrame({‘stno’:[1,2,3],‘sname’:[‘zs’,‘li’,‘ww’],‘age’:[15,16,17]})
print(df)
输出结果:
stno sname age
0 1 zs 15
1 2 li 16
2 3 ww 17
##设置索引
print(df.set_index([‘stno’,‘name’]))
输出结果:
age
stno name
1 zs 15
2 li 16
3 ww 17
###默认情况下充当列索引的数据丢弃,设置drip=False保留列数据
print(df.set_index(‘stno’,drop=False))
输出结果:
stno name age
stno
1 1 zs 15
2 2 li 16
3 3 ww 17
##append用来设置是否以追加的方式设置索引, 默认False(取代之前的索引)
##append用来设置是否以追加的方式设置索引, 默认False(取代之前的索引)
df.set_index(‘stno’,inplace=True)
print(df)
df.set_index(‘name’,inplace=True)
print(df)
输出结果:
name age
stno
1 zs 15
2 li 16
3 ww 17
age
name
zs 15
li 16
ww 17
通过设置append的参数,以追加模式添加行索引
df.set_index(‘stno’,inplace=True)
print(df)
df.set_index(‘name’,inplace=True,append=True)
print(df)
输出结果:
name age
stno
1 zs 15
2 li 16
3 ww 17
age
stno name
1 zs 15
2 li 16
3 ww 17
重置索引
reset_index是重置索引,与set_index相反,参数如下
level:重置索引层次,默认重置所有层级的索引,如果重置所有的索引,将会创建默认整数序列索引
drop:是否丢弃重置索引,默认是False
inplace:是否就地修改,默认是False
import numpy as np
import pandas as pd
df=pd.DataFrame({‘stno’:[1,2,3],‘name’:[‘zs’,‘li’,‘ww’],‘age’:[15,16,17]})
##设置层级行索引
df.set_index([‘stno’,‘name’],inplace=True)
print(df)
##重置索引,默认是重置所有层级的行级索引,重新生成整数序列作为行索引
print(df.reset_index())
输出结果:
age
stno name
1 zs 15
2 li 16
3 ww 17
stno name age
0 1 zs 15
1 2 li 16
2 3 ww 17
##重置索引后,默认将重置的行索引充当新的列,如果不想将重置后的行索引重当列,设置drop=True
import numpy as np
import pandas as pd
df=pd.DataFrame({‘stno’:[1,2,3],‘name’:[‘zs’,‘li’,‘ww’],‘age’:[15,16,17]})
##设置层级行索引
df.set_index([‘stno’,‘name’],inplace=True)
print(df)
##重置索引,默认是重置所有的行级索引
print(df.reset_index(0,drop=True))
输出结果:
age
stno name
1 zs 15
2 li 16
3 ww 17
age
name
zs 15
li 16
ww 17
分组与聚合
分组与聚合与数据库分组和聚合类似
group分组
我们可以通过group操作对Series和DataFrame对象进行分组操作,该方法返回一个分组对象,分组对象属性和方法如下
groups属性:返回一个字典类型对象,包含分组信息
size方法:返回每组记录数量
describe方法:分组查看统计信息
迭代
使用for循环对分组对象进行迭代,迭代每次返回一个元组,第一个元素为分组的key,第二个元素为该组对应的数据
分组方式:
使用groupby进行分组时,分组方式可以是一下形式:
索引名:根据该索引进行分组
索引名构成的分组:根据数组中多个索引进行分组
字典或者Seires:key指定索引,value指定分组依据,value值相等的分为一组
函数:接受索引,返回分组依据的value值
apply:对分组对象可以调用apply函数,该函数接受每个组的数据,返回操作之后的结果,apply最后将每个组的操作结果进行合并(concat)
import numpy as np
import pandas as pd
df=pd.DataFrame({‘部门’:[‘研发’,‘财务’,‘研发’,‘财务’],‘项目组’:[‘一组’,‘二组’,‘二组’,‘一组’],
‘姓名’:[‘张三’,‘李四’,‘王五’,‘赵六’],‘年龄’:[‘20’,‘21’,‘22’,‘23’],
‘利润’:[‘5’,‘10’,‘10’,‘25’]})
print(df)
输出结果:
部门 项目组 姓名 年龄 利润
0 研发 一组 张三 20 5
1 财务 二组 李四 21 10
2 研发 二组 王五 22 10
3 财务 一组 赵六 23 25
##根据部门分组
groups=df.groupby(‘部门’)
##分组对象不想列表,可以讲分组后的内容直接输出,其类型是DataFrameGroupBy object
print(groups)
##分组对象虽然不能直接输出,但是是可以迭代的对象(元组),可以通过for循环迭代每组的数据
for k,v in groups:
print(k,v)
输出结果:
研发
部门 项目组 姓名 年龄 利润
0 研发 一组 张三 20 5
2 研发 二组 王五 22 10
财务
部门 项目组 姓名 年龄 利润
1 财务 二组 李四 21 10
3 财务 一组 赵六 23 25
##通过group属性查看分组对象属性和方法(以字典形式返回结果)
print(groups.groups)
输出结果:
{‘研发’: Int64Index([0, 2], dtype=‘int64’), ‘财务’: Int64Index([1, 3], dtype=‘int64’)}
##多个索引列分组
groups=df.groupby([‘部门’,‘项目组’])
输出结果:
(‘研发’, ‘一组’) 部门 项目组 姓名 年龄 利润
0 研发 一组 张三 20 5
(‘研发’, ‘二组’) 部门 项目组 姓名 年龄 利润
2 研发 二组 王五 22 10
(‘财务’, ‘一组’) 部门 项目组 姓名 年龄 利润
3 财务 一组 赵六 23 25
(‘财务’, ‘二组’) 部门 项目组 姓名 年龄 利润
1 财务 二组 李四 21 10
##根据函数分组
##根据函数分组
##函数需要一个参数,用来接收行索引值,函数还需要有返回值,用来指定组
##根据需求将<10和>=10的人员分组,得到两组
##先将利润设置成行索引,用set_index函数
df=df.set_index(‘利润’)
def group_handle(index):
if int(index)<10:
return 0
return 1
group=df.groupby(group_handle)
for k,v in group:
print(k,v)
输出结果:
0
部门 项目组 姓名 年龄
利润
5 研发 一组 张三 20
1
部门 项目组 姓名 年龄
利润
10 财务 二组 李四 21
10 研发 二组 王五 22
25 财务 一组 赵六 23
##根据索引值分组
group=df.groupby({‘姓名’:0,‘利润’:0,‘部门’:1,‘项目组’:1},axis=1)
for k,v in group:
display(k,v)
输出结果:
0.0
姓名 利润
0 张三 5
1 李四 10
2 王五 10
3 赵六 25
1.0
部门 项目组
0 研发 一组
1 财务 二组
2 研发 二组
3 财务 一组
分组后统计
##先进行分组
group=df.groupby(‘部门’)
for k, v in group:
display(k,v)
##对分组数据统计(聚合)
display(group.sum())
输出结果:
研发
部门 项目组 姓名 年龄 利润
0 研发 一组 张三 20 5
2 研发 二组 王五 22 10
财务
部门 项目组 姓名 年龄 利润
1 财务 二组 李四 21 10
3 财务 一组 赵六 23 25
年龄 利润
部门
研发 42 15
财务 44 35
##所有数值型相加,字符串型拼接
display(df.sum())
##设置DataFrame只对数值型做统计,指定参数 numeric_only=Ture
displsy(df.sum(numeric_only=Ture))
##对分组数据中指定列数据进行统计
group=df.groupby(‘部门’)
print(group[‘利润’].sum())
输出结果:
部门
研发 15
财务 35
Name: 利润, dtype: int64
数据分组中的apply方法
对分组函数可以用apply函数,该函数接收每个组的数据,返回操作之后
的结的果,apply最后将每个组的操作结果进行合并(concat)
##对分组对象进行applly,apply接收函数实现对分组操作
##函数具有一个参数,一次接收分组数据,返回每一个分组处理的结果,然后最终apply将结果合并
##注意点:apply对于第一个分组数据会调用两次,但是不会影响我们的结果
group=df.groupby(‘部门’)
group.apply(lambda x:print(x))
输出结果:
部门 项目组 姓名 年龄 利润
0 研发 一组 张三 20 5
2 研发 二组 王五 22 10
部门 项目组 姓名 年龄 利润
0 研发 一组 张三 20 5
2 研发 二组 王五 22 10
部门 项目组 姓名 年龄 利润
1 财务 二组 李四 21 10
3 财务 一组 赵六 23 25
##对每组数据进行求和的统计x.sum()
print(group.apply(lambda x:x.sum()))
输出结果:
部门 项目组 姓名 年龄 利润
部门
研发 研发研发 一组二组 张三王五 42 15
财务 财务财务 二组一组 李四赵六 44 35
聚合中的agg方法
聚合:可以分组对象进行聚合(多个值变成一个值),例如mean(),sum()等
除此之外,我们可以调用agg方法,实现自定义聚合方式,函数接受一行或者一列数据,返回该行或者列的聚合后的结果。
##agg方法实现对DataFrame,分组对象的聚合,可以传入四种参数,字符串,字典,列表,函数
##创建对象
df=pd.DataFrame({‘部门’:[‘研发’,‘财务’,‘研发’,‘财务’],‘项目组’:[‘一组’,‘二组’,‘二组’,‘一组’],
‘姓名’:[‘张三’,‘李四’,‘王五’,‘赵六’],‘年龄’:[20,21,22,23],
‘利润’:[5,10,10,25]})
##分组
group=df.groupby(‘部门’)
##1,传入字符串
print(df.agg(‘mean’,numeric_only=True),df.agg(‘sum’,numeric_only=True))
输出结果:
年龄 21.5
利润 12.5
dtype: float64
年龄 86
利润 50
dtype: int64
##2,多个字符串构成的列表
print(df.agg([‘sum’,‘mean’]))
输出结果:
部门 项目组 姓名 年龄 利润
sum 研发财务研发财务 一组二组二组一组 张三李四王五赵六 86.0 50.0
mean NaN NaN NaN 21.5 12.5
##agg的四种传入方式,3传入字典 {k1:v1}
print(df.agg({‘利润’:[‘sum’,‘mean’],‘年龄’:[‘max’,min]}))
输出结果:
利润 年龄
max NaN 23.0
mean 12.5 NaN
min NaN 20.0
sum 50.0 NaN
print(group.agg([‘mean’,‘sum’]))
输出结果:
年龄 利润
mean sum mean sum
部门
研发 21 42 7.5 15
财务 22 44 17.5 35