Pandas统计函数与分组函数
目录
series与dataframe的统计函数
count,sum,prod,min,max,first,last,mean,median(中位数),std(标准差),var(方差),mad(均值绝对偏差)
describe
import numpy as np
import pandas as pd
a=pd.DataFrame({"a":["i","j","k","i","j","k"],"b":[2,1,4,1,2,4],"c":[3,2,2,1,2,3]})
a
a b c 0 i 2 3 1 j 1 2 2 k 4 2 3 i 1 1 4 j 2 2 5 k 4 3
a.mean()
b 2.333333 c 2.166667 dtype: float64
a.sum()
a ijkijk b 14 c 13 dtype: object
二维数据下统计的方向性
a.sum(axis=1)
0 5 1 3 2 6 3 2 4 4 5 7 dtype: int64
这是一个集成统计函数
a.describe()
b c count 6.000000 6.000000 mean 2.333333 2.166667 std 1.366260 0.752773 min 1.000000 1.000000 25% 1.250000 2.000000 50% 2.000000 2.000000 75% 3.500000 2.750000 max 4.000000 3.000000
自定义的集成统计函数
a.agg(["min","max","sum","std","median"])
a b c min i 1.00000 1.000000 max k 4.00000 3.000000 sum ijkijk 14.00000 13.000000 std NaN 1.36626 0.752773 median NaN 2.00000 2.000000
最有用的数据分析函数——groupby
from IPython.display import Image
Image("timg.jpg")
a
a b c 0 i 2 3 1 j 1 2 2 k 4 2 3 i 1 1 4 j 2 2 5 k 4 3
a.groupby("a")
<pandas.core.groupby.groupby.DataFrameGroupBy object at 0x000000D816B8ED68>
groupby的迭代
for i in a.groupby("a"): print(i[0]) print(i[1]) print()
- 分组后的结果可以看成生成了一个新的数据框,原来的a列作为了第二层键,和原来的键构成了一个二层索引结构的数据框
- 注意,groupby之后默认都是会按照对应列元素从小到大进行排序的,如果不希望排序需要在参数中设置sort=False
a b c 0 i 2 3 3 i 1 1 a b c 1 j 1 2 4 j 2 2 a b c 2 k 4 2 5 k 4 3
对两列数据分组
for i in a.groupby(["a","c"]): print(i[0]) print(i[1]) print()
('i', 1) a b c 3 i 1 1 ('i', 3) a b c 0 i 2 3 ('j', 2) a b c 1 j 1 2 4 j 2 2 ('k', 2) a b c 2 k 4 2 ('k', 3) a b c 5 k 4 3
groupby的切片
a.groupby("a").get_group("j")
a b c 1 j 1 2 4 j 2 2
groupby后直接进行统计
for i in a.groupby("a"): print(i[1]) print()
正是因为分组后的结果本质上是一个二层索引的数据框,它继承数据框的统计函数就是理所当然的
a b c 0 i 2 3 3 i 1 1 a b c 1 j 1 2 4 j 2 2 a b c 2 k 4 2 5 k 4 3
a1=a.groupby("a")
但是和在原来数据框中进行统计相区别,这里只有一种统计方式,不分组的时候是统计整列,这里把一列分成若干部分统计
a1.sum()
b c a i 3 4 j 3 4 k 8 5
a1["b"].sum()
a i 3 j 3 k 8 Name: b, dtype: int64
a1.describe()
b c count mean std min 25% 50% 75% max count mean std min 25% 50% 75% max a i 2.0 1.5 0.707107 1.0 1.25 1.5 1.75 2.0 2.0 2.0 1.414214 1.0 1.50 2.0 2.50 3.0 j 2.0 1.5 0.707107 1.0 1.25 1.5 1.75 2.0 2.0 2.0 0.000000 2.0 2.00 2.0 2.00 2.0 k 2.0 4.0 0.000000 4.0 4.00 4.0 4.00 4.0 2.0 2.5 0.707107 2.0 2.25 2.5 2.75 3.0
a1.agg(["sum","mean"])
b c sum mean sum mean a i 3 1.5 4 2.0 j 3 1.5 4 2.0 k 8 4.0 5 2.5
过滤
这里的x为已经groupby之后的数据,groupby之后,谁的b列的和大于3?
def gl(x): return x["b"].sum()>3 a1.filter(gl)
最终结果是满足条件的原始记录
a b c 2 k 4 2 5 k 4 3
transform与apply
简而言之apply更好用
a1.mean()
b c a i 1.5 2.0 j 1.5 2.0 k 4.0 2.5
for i in a.groupby("a"): print(i[1]) print()
a b c 0 i 2 3 3 i 1 1 a b c 1 j 1 2 4 j 2 2 a b c 2 k 4 2 5 k 4 3
a1.transform(lambda x:x-x.mean())
b c
0 0.5 1.0 1 -0.5 0.0 2 0.0 -0.5 3 -0.5 -1.0 4 0.5 0.0 5 0.0 0.5
a1.apply(lambda x:x-x.mean())
在某些时候apply和transform结果是一样的
b c 0 0.5 1.0 1 -0.5 0.0 2 0.0 -0.5 3 -0.5 -1.0 4 0.5 0.0 5 0.0 0.5
a1.transform(lambda x:x.sum())
b c 0 3 4 1 3 4 2 8 5 3 3 4 4 3 4 5 8 5
a1.apply(lambda x:x.sum())
apply默认作用到所有列,transform只作用到b,c列,transform得到的结果始终是和原来的索引结构一样,而apply则在值相同的时候会归总
a b c a i ii 3 4 j jj 3 4 k kk 8 5
a1.apply(lambda x:x["b"]-2)
a i 0 0 3 -1 j 1 -1 4 0 k 2 2 5 2 Name: b, dtype: int64
a1.transform(lambda x:x["c"]-3)
transform的运算始终只调用x而不能是x某一列
a
a b c 0 i 2 3 1 j 1 2 2 k 4 2 3 i 1 1 4 j 2 2 5 k 4 3
自定义分组
a
a b c 0 i 2 3 1 j 1 2 2 k 4 2 3 i 1 1 4 j 2 2 5 k 4 3
g=[1,1,1,0,0,0]#列表的顺序和这个数据框的行标是匹配的
for i in a.groupby(g): print(i[1]) print()
a b c 3 i 1 1 4 j 2 2 5 k 4 3 a b c 0 i 2 3 1 j 1 2 2 k 4 2
g1=a["b"] for i in a.groupby(g1): print(i[1]) print()
a b c 1 j 1 2 3 i 1 1 a b c 0 i 2 3 4 j 2 2 a b c 2 k 4 2 5 k 4 3
g1=a["b"]%2 for i in a.groupby(g1): print(i[1]) print()
这样我们通过已知列生成新列,然后在新列上进行分组
a b c 0 i 2 3 2 k 4 2 4 j 2 2 5 k 4 3 a b c 1 j 1 2 3 i 1 1