python科学计算的基本方式:
向量化运算(矢量化运算),并行计算,摒弃了循环遍历(标量运算),浪费内存
衡量一个人会不会用pandas做数据分析
- 会不会做聚合推导透视表,交叉表
- 会不会矢量化编程完成项目
自定义运算
apply():Series和DataFrame通用自定义运算函数(计算行/列)
map():Series用
applymap():DataFrame用计算单元格
如果pandas库自带的运算和函数不满足需求,可以自定义函数,并同时将函数应用到pandas的每行/列或值上
应用函数主要用于替代传统的for循环
可以将map和apply的参数x理解为for循环的i值(series就是单值,DataFrame就是每一行/列)
针对Series的map函数,会将自定义函数应用到Series对象的每个值
不直接用于单元格的算法
关于行列的思路,分割成每个单元格作比较
参数传递
-
apply(top, n=1, column='math') 在apply函数内定义参数,帮助传入top内 def top(aa,n,columns='english')
axis=0按行操作,默认
- 给这一列的所有行,进行运算
axis=1按列操作
- 给这一行的所有列,进行运算
a = pd.Series([9,7,8,6],['a','b','c','d']) b = pd.DataFrame(np.arange(20).reshape(4,5),index=['a','b','c','d']) def ccc(x): return x.min() b.apply(ccc, axis=0) #给这一列的所有行,进行运算,所以结果和想的不一样 # 自定义函数的参数x,用apply调用,在运算过程中标识DataFrame的1行或者1列(是series对象,可以理解为for循环遍历,但是并行运算) def bbb(x): return pd.Series([x.min(),x.max()],index=['min','max']) #构建Series返回,结果就是返回DataFrame b.apply(bbb)
基本统计函数
pandas的统计运算方法和numpy基本一致
默认针对0轴(行)做运算,大部分函数可加参数axis-1改为列运算
- describe() 针对0轴的统计汇总,计数/平均值/标准差/最小值/四分位数/最大值,非数值型列,不计入(字符串)指标
- sum()计算数据的总和,按针对0轴计算(各行计算),针对1轴计算参数改为1
- count() 非nan值数量
- mean()/median()/mode() 计算数据的算数平均值/中位数/众数
- var()/std() 计算数据的方差/标准差
- min()/max() 计算数据的最大值/最小值
- idxmin()/idxmax() 计算数据的第一个最大值/最小值所在的位置索引,给索引切片使用(自定义索引,排除null/na等空值)
pandas分组聚合-基础
数据分析阶段
数据规律(清洗阶段后),下一个阶段就是分组聚合,分组聚合只针对数值类型
- 对数据集分组并对各组应用一个函数是数据分析中的重要环境
- 一般将数据准备好后,首先就是计算分组统计
- sql能够方便的连接,过滤。转换和聚合数据,但sql能执行的分组运算种类优先,pandas则强大灵活很多
聚合操作,一般是指应用某种方法(自定义的聚合函数或者系统自带的pandas的统计方法等)给数据降维
聚合函数常用
- 平均值:mean() 透视表
- 个数:size() 交叉表、
分组的作为行索引,聚合作为值(series),聚合作为列索引(DataFrame)
数据分组 分组聚合:groupby(),一般指以下一个或者多个操作步骤的集合 splitting 分组:将列分割为n组 applying 应用:将每个分组应用聚合函数 combining合并:合并分组和聚合的结果 name,score name ,score name ,score a 1 a 1,2 a 2 a 2 ====> b 3,4 ===> b 4 b 3 group by name max(score) b 4
以单列基准分组,聚合其他
a_values = [{"name": "锺洋","chinese": 23,"math": 25,"english": 25,"test": "一" },{"name": "李敏","chinese": 99,"math": 48,"english": 78,"test": "一" },{"name": "夏军","chinese": 70,"math": 83,"english": 12,"test": "一" },{"name": "姚明","chinese": 65,"math": 12,"english": 73,"test": '二' },{"name": "夏军","chinese": 80,"math": 63,"english": 45,"test": '二' },{"name": "夏军","chinese": 90,"math": 82,"english": 65,"test": '三' },{"name": "李帅","chinese": 99,"math": 58,"english": 78,"test": "一"}] df = pd.DataFrame(a_values) # 每位同学每课成绩的平均分 # 分组 x = df.groupby('name').mean() # 每位同学考试的次数 y = df.groupby('name').size() # 将分组传递给变量 class_group = df.groupby('name') class_group.size() # 如果不想使用分组作为列索引,设置参数as_index=False x = df.groupby('name',as_index=False).mean()
以多列为基准
- 多列分组
- 单列或多列聚合
# 单列多列分组 df.groupby('name').mean() df.groupby(['name','test']).mean()
多列单列聚合
- 对于大数据集,很可能值需要对部分进行聚合
- 下面三种写法结果一样
- 分组聚合参数,传入标量形式得单个列名,返回Series
- 分组聚合参数,传入列表或数组,返回DataFrame(默认传入所以列)
# 对除分组基准列以外得所有列进行聚合 df.groupby('name').sum() # 多列聚合, 聚合除分组以外得所有列 # 分组后,只对chinese单列聚合 df['chinese'].groupby(df['name']).sum() # 效率高,但是写法诡异 df.groupby('name')['chinese'].sum() # 书写简单,效率高,推荐,返回Series df.groupby('name')[['chinese']].sum() # 书写简单,效率高,推荐,返回DataFrame # 分组后,多列聚合 df.groupby('name')['chinese'].sum() # 书写简单,效率高,推荐
分组聚合进阶
本质上 groupby传入得数据并不是行索引或列索引,而是任意一个和数据结构对应得序列(布尔,列表,数组,字典,Series)
- 根据列表做分组基准
- 根据字典或者Series做分组基准
- 根据函数做分组基准
- 根据层次化索引得级别做分组基准
# 根据列表分组,列表值得个数必须和表格行或列数对应 df.groupby('name').size() #分组参数是列索引,直接获取某列得值 df.groupby(df['name']).size() #手动将列值传入分组参数 ### df_list = ['aa','bb','cc','dd','ee','ff','gg'] # 自定义列表作为分组基准 df.groupby(df_list).size() #set_index把其中一列作为行索引 mapping = {'李敏':'one','姚明':'two'} df2 = df.set_index('name') df2.groupby(mapping).sum() # 使用seies进行分组 df2.groupby(pd.Series(mapping)).size()
通过函数分组
- 比起字典或者series,函数是一种更原生得方法定义分组映射
- 任何被当作分组键得函数都会在各个索引值上被调用一次,其返回值就会被作用分组基准
people = pd.DataFrame( np.random.randn(5,5), columns=['a','bc','c','d','e'], index=['Joe','Steve','wes','jim','travis'] ) people.iloc[2:3,[1,2]] = np.nan # len把行索引字符得个数作为分组基准 people.groupby(len).sum() # a = [3,5,3,3,6] people.groupby(a).sum() # ccc = ['one','one','one','two','two'] people.groupby([len,ccc]).sum() #joe wes既有3个字符,又属于one ,针对行索引做的分组
#使用函数分组 people.groupby(len,axis=1).sum() # zzz = ['one','one','one','two','two'] people.groupby([len,zzz],axis=1).sum()
# lianxi,输出每个学生在每次考次数中得数学平均分
从一个原始大表中抽取一个符合需求得小标
df.groupby(['name','test']).mean() # 3维度 df.groupby(['name','test'])['math'].mean() #2维Series pd.DataFrame(df.groupby(['name','test'])['math'].mean() ) df.groupby(['name','test'])['math'].mean().unstack().fillna(0).astype(np.int) #2维series转换DataFrame
df.groupby(['name','test'])['math'].mean().unstack().fillna(0).astype(np.int) #2维series转换DataFrame # 称之为透视表 抽出1列,分组后作为行索引 抽出1列,分组后作为列索引 抽出1列,平均值聚合后作为值
根据层次化索引得级别分组
要根据层次化索引得级别,使用level关键字传递级别序号或名字
colums = pd.MultiIndex.from_arrays([['US','US','US','JP','JP',],[1,3,5,1,3]],names=['city','tenor']) hier_df = pd.DataFrame(np.random.randn(4,5),columns=colums) hier_df.groupby(level='city',axis=1).sum() #默认按照行分组 # 按行分组,自定义布尔数组做分组基准 ddd = [True,True,False,False,False,False,True] df.groupby(ddd).sum() # 按照列分组 ddd = [True,True,False,False,False] df.groupby(ddd,axis=1).sum() # 按列分组,自定义布尔数组做分组基准 df.groupby(df.dtypes,axis=1).sum()
#假设以知列得分组关系后,并希望根据分组计算列得和 mapping={'a':'red','bc':'red','c':'bule','d':'bule','e':'red','f':'orange' } # 多写或少写不会执行,多了一个f,不会影响分组 people.groupby(mapping,axis=1).sum()