数据集合与分组操作:GroupBy 机制,历遍各组, 选择一列或所有列的子集, 使用字典和series分组, 使用函数分组, 根据索引层级分组

对数据集进行分类,并在每一组上应用一个聚合函数或转换函数。在载入,合并,准备数据集后需要计算分组统计或者数据透视表用于报告或可视化的目的。pandas提供了一个灵活的groupby接口,允许你以一种自然的方式对数据集进行切片,切块和总结。

1.1 GroupBy 机制

数据包含在pandas对象中,可以是series or dataframe 或其他数据结构,之后根据你提供的一个或多个键分离到各个组中,分离操作是在数据对象的特定轴上进行的。例如,datafrme可以在行方向(axis=0) 或列方向(axis=1)进行分组。分组操作后对各个组应用函数产生新值,组合结构联合成一个结果对象。

在这里插入图片描述

分组键可以是多种形式,并且键不一定是相同的类型:

  • 与需要分组的轴向长度一致的值列表或值数组
  • dataframe的列名
  • 可用将分组轴向 上的值和分组名称相匹配的字典或series。
  • 可以在轴索引或索引中的单个标签上调用的函数。
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)})
	key1	key2	data1	data2
0	a	one	0.784580	0.966883
1	a	two	0.023604	-0.488664
2	b	one	1.974237	0.845493
3	b	two	0.588121	0.564195
4	a	one	0.643017	0.255800

grouped=df['data1'].groupby(df['key1'])     # 根据key1标签计算data1列的均值。可以使用groupby方法
grouped                       # 得到一个GroupBy 对象。除了一些关于分组件df['key1'] 的一些中间数据之外,还没进行计算。
<pandas.core.groupby.generic.SeriesGroupBy object at 0x000001E641692CC8>
 # 这个对象有所有必须的信息,可以在每一个分组上进行一些操作。

grouped.mean()							# 调用GroupBy 的mean 方法求平均值。
key1
a    0.483734
b    1.281179       # 数据(一个series)根据分组键进行了聚合,并产生一个新的series,这个series使用key1 列的唯一值作为索引
Name: data1, dtype: float64      


means=df['data1'].groupby([df['key1'],df['key2']]).mean()     # 将多个数组作为列表传入。
means                    # 使用两个键对数据进行分组,并且结果 series 含有多层索引。
key1  key2                  # 感觉这个groupby 就是将后面的参数变成索引,然后索引相同的进行计算。。。。
a     one     0.713799
      two     0.023604
b     one     1.974237
      two     0.588121
Name: data1, dtype: float64

means.unstack()
key2	one	two
key1		
a	0.713799	0.023604
b	1.974237	0.588121

states=np.array(['Ohio','California','California','Ohio','Ohio'])
years=np.array([2005,2005,2006,2005,2006])          # 分组键可以是正确长度的任意数组。
df['data1'].groupby([states,years]).mean()
California  2005    0.023604
            2006    1.974237
Ohio        2005    0.686350
            2006    0.643017
Name: data1, dtype: float64

df.groupby('key1').mean()               # 分组信息作为你想要继续处理的数据,通常包含在同一个dataframe中。
  										# 这种情况下,你可以传递列名作为分组键
       data1	data2
key1		
a	0.483734	0.244673                  # 可用看见这里没有key2 列,这是因为df['key2'] 并不是数值列,排除。。
b	1.281179	0.704844                     # 啊。。怎么排除的。。

df.groupby(['key1','key2']).mean()

               data1	data2
key1 key2		
a	 one	0.713799	0.611341
     two	0.023604	-0.488664
b	 one	1.974237	0.845493
     two	0.588121	0.564195


df.groupby(['key1','key2']).size()      # 通用的方法,返回包含组大小信息的series
key1  key2
a     one     2
      two     1
b     one     1
      two     1
dtype: int64

分组键中的任何缺失值将被排除在结果之外。

1.1.1 历遍各组

GroupBy 对象支持迭代,会生成一个包含组名和数据块的2维元组序列。

for name,group in df.groupby('key1'):
    print(name)
    print(group)

a
  key1 key2     data1     data2
0    a  one  0.784580  0.966883
1    a  two  0.023604 -0.488664
4    a  one  0.643017  0.255800
b
  key1 key2     data1     data2
2    b  one  1.974237  0.845493
3    b  two  0.588121  0.564195

for (k1,k2),group in df.groupby(['key1','key2']):
    print((k1,k2))
    print(group)

('a', 'one')
  key1 key2     data1     data2
0    a  one  0.784580  0.966883
4    a  one  0.643017  0.255800
('a', 'two')
  key1 key2     data1     data2
1    a  two  0.023604 -0.488664
('b', 'one')
  key1 key2     data1     data2
2    b  one  1.974237  0.845493
('b', 'two')
  key1 key2     data1     data2
3    b  two  0.588121  0.564195


pieces =dict(list(df.groupby('key1')))       # 转换成字典,选择在任何一块数据上进行操作,
pieces['b']
  key1	key2	data1	data2
2	b	one	1.974237	0.845493
3	b	two	0.588121	0.564195


# 默认情况下,groupbt 在axis-0 的轴向上分组,也可以在其他任意轴向上进行分组,
df.dtypes
key1      object
key2      object
data1    float64
data2    float64
dtype: object

grouped=df.groupby(df.dtypes,axis=1)
for dtype,group in grouped:
    print(dtype)
    print(group)
float64
      data1     data2
0  0.784580  0.966883
1  0.023604 -0.488664
2  1.974237  0.845493
3  0.588121  0.564195
4  0.643017  0.255800
object
  key1 key2
0    a  one
1    a  two
2    b  one
3    b  two
4    a  one

1.1.2 选择一列或所有列的子集

将从dataframe 创建的GroupBy 对象用列名称或列名称数组进行索引时,会产生用于聚合的列子集的效果。

df.groupby('key1')['data1'].size() # == df['data1'].groupby(df['key1'])
key1
a    3
b    2
Name: data1, dtype: int64
df.groupby('key1')[['data2']].size()      # == df[['data2']].groupby(df['key1'])

df.groupby(['key1','key2'])[['data2']].mean()
		data2
key1	key2	
a	one	0.611341                  # 返回dataframe 的形式
    two	-0.488664
b	one	0.845493
    two	0.564195
 
 # 如果传递的是列表或数组,则此索引操作返回的对象是分组的dataframe,如果只有单个列作为标量传递,则为分组的sereis。

s_grouped=df.groupby(['key1','key2'])['data2']
s_grouped
<pandas.core.groupby.generic.SeriesGroupBy object at 0x000001E641A5E248>
s_grouped.mean()
key1  key2
a     one     0.611341         # seres 的形式
      two    -0.488664
b     one     0.845493
      two     0.564195
Name: data2, dtype: float64

1.1.1 使用字典和series分组

分组信息可能会以非数组形式存在。

people=pd.DataFrame(np.random.randn(5,5),columns=['a','b','c','d','e'],
                   index=['Joe','Steve','Wes','Jim','Travis'])
people.iloc[2:3,[1,2]]=np.nan
people
	a	b	c	d	e
Joe	0.212254	0.167760	0.478722	1.340769	1.287925
Steve	-1.071535	1.101858	-2.195090	0.306472	1.000913
Wes	-0.358333	NaN	NaN	-0.155213	1.126299
Jim	1.286113	-0.886354	-0.488328	-0.131525	1.012031
Travis	0.042763	-0.425792	-0.758249	0.185632	1.143018

mapping={'a':'red','b':'red','c':'blue','d':'blue','e':'red','f':'orange'}   # 建立个列的分组关系,然后累加 
people.groupby(mapping,axis=1).sum()         # 添加的f 是表示为用的分组键也是莫问题的。。
            blue	red
Joe	    1.819491	1.667939
Steve	-1.888619	1.031236
Wes	    -0.155213	0.767966
Jim  	-0.619853	1.411790
Travis	-0.572617	0.759989

map_series=pd.Series(mapping)
map_series
a       red
b       red
c      blue
d      blue
e       red
f    orange
dtype: object

people.groupby(map_series,axis=1).count()
	  blue	red
Joe	    2	3
Steve	2	3
Wes	    1	2
Jim	    2	3
Travis	2	3

1.1.4 使用函数分组

作为分组键传递的函数将会按照每个索引值调用一次,同时返回值会被用作分组名称。就如上面那个例子,以人的名字作为索引值,以名字长度进行分组。虽然可用计算出字符串长度的数组,但是传递len函数更加简单,

people.groupby(len).sum()
       a	      b	         c	         d	         e
3	1.140035	-0.718594	-0.009606	1.054031	3.426255
5	-1.071535	1.101858	-2.195090	0.306472	1.000913
6	0.042763	-0.425792	-0.758249	0.185632	1.143018

key_list=['one','one','one','two','two']
people.groupby([len,key_list]).min()         # 将函数与数组,字典或series进行混合,所有对象都会在内部转换为数组。
	               a	b	c	d	e
3	one	-0.358333	0.167760	0.478722	-0.155213	1.126299
    two	1.286113	-0.886354	-0.488328	-0.131525	1.012031
5	one	-1.071535	1.101858	-2.195090	0.306472	1.000913
6	two	0.042763	-0.425792	-0.758249	0.185632	1.143018

1.1.5 根据索引层级分组

能够在轴索引的某个层级上进行聚合,这就很方便

columns=pd.MultiIndex.from_arrays([['US','US','US','JP','JP'],
                                  [1,3,5,1,3]],
                                 names=['city','tenor'])
hief_df=pd.DataFrame(np.random.randn(4,5),columns=columns)
hief_df

city	US	          JP
tenor	1	3	5	1	3
0	0.203905	0.337928	1.020350	0.712070	1.372785
1	-0.556021	-0.490895	-0.051140	-1.117818	-1.368995
2	-1.012746	0.855241	0.037147	1.202405	0.763244
3	-0.118763	0.815760	-2.313174	-0.549343	0.318364

hief_df.groupby(level='city',axis=1).count()
city	JP	US
0	2	3
1	2	3
2	2	3
3	2	3
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值