pandas之数据运算

python科学计算的基本方式:

向量化运算(矢量化运算),并行计算,摒弃了循环遍历(标量运算),浪费内存
衡量一个人会不会用pandas做数据分析

  1. 会不会做聚合推导透视表,交叉表
  2. 会不会矢量化编程完成项目

自定义运算
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改为列运算

  1. describe() 针对0轴的统计汇总,计数/平均值/标准差/最小值/四分位数/最大值,非数值型列,不计入(字符串)指标
  2. sum()计算数据的总和,按针对0轴计算(各行计算),针对1轴计算参数改为1
  3. count() 非nan值数量
  4. mean()/median()/mode() 计算数据的算数平均值/中位数/众数
  5. var()/std() 计算数据的方差/标准差
  6. min()/max() 计算数据的最大值/最小值
  7. 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()

 

posted @ 2020-06-03 14:17  亚洲哈登  阅读(859)  评论(0编辑  收藏  举报