Pandas统计函数与分组函数

来自CloudWiki
跳转至: 导航搜索

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")

bd20-3-1.png

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