数据聚合与分组运算
df = pd.DataFrame({'key':['a','b','a','a'],'data':np.random.randint(1,10,4)}) df # groupby的本质 groupd = df['data'].groupby(df['key']) groupd # Groupby技术,另一个术语解释就是 split-apply-combine # 第一阶段 根据你所提供的一个或多个键被拆分为多组 # 第二阶段 将一个函数应用到各个分组上,并产生以个新值 # 第三阶段 所有这些函数的执行结果被合并到最终的结果对象中 # groupd 是GroupBy对象。它实际上还没有进行任何计算,只是含有一些有关分组键df['key']的中间数据而已。换句话说,该对象 # 已经有了接下来对各分组执行运算所需的一切信息。 # 这里最重要的是,数据根据分组键进行聚合,产生了一个新的Series,其索引为key列中的惟一值。 # groupby 的语法糖 # 对于由DataFrame产生的GroupBy对象,如果用一个或一组列名对其进行索引,就能实现选取部分列 # 进行聚合的目的。 df.groupby(df['key1'])['data1'] # 是以下代码的语法糖 df['data1'].groupby(df['key1']) # groupby + 函数 # 相对于字典或Series,python函数在定义分组映射关系时可以更有创意且更为抽象。 # 任何被当做分组键的函数都会在各个索引值上被调用一次,其返回值就会被当做分组名称。 # 假如你希望根据人名的长度进行分组,虽然可以求取人格字符串长度数组,但其实仅仅 # 传入一个len函数就可以了。高,实在是高。 people.groupby(len).sum() # 数据聚合 # 对于聚合,我指的是任何能够从数组中产生标量值的数据转换过程,比如,max(),min()。 # 然而,并不是只能是使用这些方法,你可以使用自己发明的聚合运算,还可以调用分组对象 # 上已经定义好的任何方法。例如,quantile() # 虽然quantile没有明确的实现与groupby对象,但它是一个series方法,所以这里是能用的。 # 实际上,GroupBy会高效的对Series进行切片,然后对各片调用piece,quantile,最终将这些结果 # 组装成最终结果。 df['data1'].group(df['key1']).quantile(0.9) # 如果使用自己的聚合函数,只需将其传入agg方法或aggregate方法 f['data1'].group(df['key1']).agg(peak_to_peak) # 分组级运算和转换 # 聚合只不过是分组运算的其中一种而已,它是数据转换的一个特例,也就是说,它接受 # 能够将一维数组简化为标量值的函数。 # 而transform和apply方法,它们能够执行更多其它的分组运算。 # 跟aggregate一样,transform也是一个有这严格条件的特殊函数:传入的函数只能产生两种结果: # 要么产生一个可以广播的标量值,如np.mean,要么产生一个相同大小的结果数组。 # 最一般化的GroupBy方法是apply。 # apply会将待处理的对象拆分成多个片段,然后对各片段调用传入的函数,最后尝试将各 # 片段组合到一起。 def top(df,n=5,column='tip_pct'): return df.sort_index(by=column)[-n:] tips.groupby('smoker').apply(top,n=6,column='total_pill') # 这里发生了什么? # top函数在DataFrame的各个片段上调用,然后由pandas.concat连接在一起,并以分组名称进行了标记。 # 于是最终结果就有了一个层次化索引。 # 如果传给apply的函数能够接受其它参数或关键字,则可以将这些内容放在函数名后面一并传入。 # 除了这些基本用法之外,能否充分发挥apply的威力很大程度上取决于你的创造力。传入的 # 那个函数能够做什么全由你说了算,它只需要返回一个pandas对象或标量值即可。 # 透视表和交叉表 # 透视表是一种常见的数据汇总工具。它根据一个或多个键对数据进行聚合,并根据行和列上的分组键 # 将数据分配到各个矩形区域中。在python和pandas中。可以通过groupby功能重塑运算制造透视表。 # DataFrame有一个pivot_table方法,可以实现透视功能。 # 应用场景还是很广的。 tips.pivot_table(values,rows=,cols=,aggfunc=,fill_value=,margins=) # 交叉表 crosstab # 交叉表是一种用于计算分组频率的特殊透视表。功能就很单一了,只是将某个矩形区域内计数。 pd.crosstab([tips.time,tips.day],tips.smoker,margins=True) # [tips.time,tips.day] 相当于 rows # tips.smoker 相当于 cols