pandas和R中的groupby

groupby 可以根据一个数据框的部分数据,将整个数据框进行分组,简称:聚合。聚合之后,可以按组进行对数据进行统计分析。

pandas

1
2
3
4
5
6
7
8
9
10
11
12
13
In [10]: df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
....: 'key2' : ['one', 'two', 'one', 'two', 'one'],
....: 'data1' : np.random.randn(5),
....: 'data2' : np.random.randn(5)})

In [11]: df #建立一个Dataframe数据框
Out[11]:
data1 data2 key1 key2
0 -0.204708 1.393406 a one
1 0.478943 0.092908 a two
2 -0.519439 0.281746 b one
3 -0.555730 0.769023 b two
4 1.965781 1.246435 a one
1
2
3
4
In [12]: grouped = df.groupby('key1')  #按key1进行分组

In [13]: grouped #得到的grouped一个简单处理的可迭代对象(GroupBy),实际上还没有进行任何计算
Out[13]: <pandas.core.groupby.DataframeGroupBy object at 0x0000000000FF07EB8>
1
2
3
4
5
6
In [14]: grouped.mean()  #调用GroupBy的mean方法来计算分组平均值:
Out[14]:
data1 data2
key1
a 0.114474 0.714913
b 0.300820 -1.160967
1
2
3
4
5
6
7
8
9
10
In [15]: means = df.groupby(['key1', 'key2']).mean()['data1']  #按key1和key2分组,选出data1数据

In [16]: means
Out[16]:
key1 key2
a one 0.880536
two 0.478943
b one -0.519439
two -0.555730
Name: data1, dtype: float64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [35]: people = pd.DataFrame(np.random.randn(5, 5),
....: columns=['a', 'b', 'c', 'd', 'e'],
....: index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])

In [36]: people.iloc[2:3, [1, 2]] = np.nan # Add a few NA values

In [37]: people #另建一个数据框,拥有index名
Out[37]:
a b c d e
Joe 1.007189 -1.296221 0.274992 0.228913 1.352917
Steve 0.886429 -2.001637 -0.371843 1.669025 -0.438570
Wes -0.539741 -2.001001 -2.001002 -1.021228 -0.577087
Jim 0.124121 0.302614 0.523772 0.000940 1.343810
Travis -0.713544 -0.831154 -2.370232 -1.860761 -0.860757
1
2
3
4
5
6
In [44]: people.groupby(len).sum() #用python函数分组将使用index
Out[44]:
a b c d e
3 0.591569 -0.993608 0.798764 -0.791374 2.119639
5 0.886429 -2.001637 -0.371843 1.669025 -0.438570
6 -0.713544 -0.831154 -2.370232 -1.860761 -0.860757

聚合运算方法

1
2
3
4
5
6
7
8
In [54]: def peak_to_peak(arr):
....: return arr.max() - arr.min()
In [55]: grouped.agg(peak_to_peak) #使用自己的聚合函数,将其传入aggregate或agg方法
Out[55]:
data1 data2
key1
a 2.170488 1.300498
b 0.036292 0.487276
1
2
3
4
5
6
7
In [69]: grouped.agg(['mean','size']) #使用多个统计方法

In [69]: ftuples = [('fuc1', 'mean'),('fuc2', np.var)] #使用自定义的名字
In [70]: grouped.agg(ftuples)

In [71]: grouped.agg({'data1' : ['min', 'max', 'mean', 'std'], #不同列可以指定不同的统计方法
....: 'data2' : ['sum']})

R

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
library(dplyr)  #group_by和summarise都在dplyr包中
data <- data.frame(year = rep(2016:2017,6),month = seq(1:12),sales=rep(c(10,20,30,40),3))
year month sales
1 2016 1 10
2 2017 2 20
3 2016 3 30
4 2017 4 40
5 2016 5 10
6 2017 6 20
7 2016 7 30
8 2017 8 40
9 2016 9 10
10 2017 10 20
11 2016 11 30
12 2017 12 40
planes <- group_by(data, year) #按年分组
delay <- summarise(planes,
count = n(), #个数
max_mon = max(month), #最大值
min_mon = min(month), #最小值
avg_sales = mean(sales), #平均值
sum_sales = sum(sales)) #求和
# A tibble: 2 x 6
year count max_mon min_mon avg_sales sum_sales
<int> <int> <dbl> <dbl> <dbl> <dbl>
1 2016 6 11 1 20 120
2 2017 6 12 2 30 180

常用的摘要函数

1
2
3
mean()    sd()    min()    max()    first()    last()    n()    sum()
median() #中位数
quantile() #分位数,quantile(x,0.25)将会找出x从小到大排列,在25%时的数

聚合函数和逻辑筛选结合

1
2
3
4
5
6
7
8
9
10
delay <- summarise(planes,
avg_sales_1 = mean(sales,na.rm=TRUE),
#na.rm=TRUE,遇到NA值时不处理,因为统计时R默认NA值会传播,python不会
avg_sales_2 = mean(sales[sales>10],na.rm=TRUE) #加入逻辑判断
planes <- group_by(data, year) #按年分组
# A tibble: 2 x 3
year avg_sales_1 avg_sales_2
<int> <dbl> <dbl>
1 2016 20. 30.
2 2017 30. 30.
1
2
3
4
5
6
In    [53]: grouped = df[df.data1>0].groupby('key1')  #逻辑筛选后按key1进行分组
Out [53]:
data1 data2
key1
a 0.679126 1.013678
b 0.300820 -1.160967