文章数据
收藏(次)

【python数据分析】第十章 数据聚合与分组运算

加关注
pandas提供灵活高效的gruopby功能,能以一种自然的方式对数据集进行切片、切块、摘要等操作
--------------------------------------------------------------------------------
df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two','one'],
'data1' : [2,8,4,2,6],
'data2' : [1,7,4,3,5]})
--------------------------------------------------------------------------------
现在想对data1按照key1的分组进行每一组的平均值
--------------------------------------------------------------------------------
group2 = df['data1'].groupby(df['key1'])
group2.mean()
输出:
key1
a 5.333333
b 3.000000
Name: data1, dtype: float64
--------------------------------------------------------------------------------
不一定按照key1分组,可以自定义分组,比如下面的,只要传递的值相同就认为时一组。
grouped = df['data1'].groupby(['g1', 'g1', 't', 't', 'c']) # 长度必须和原数据相同
--------------------------------------------------------------------------------
grouped = df['data1'].groupby(pd.Index(['g1', 'g1', 't', 't', 'c'], name='mygroup'))
grouped.mean()
mygroup ---- 指定的name在这里,上面groupby(df['key1']) 是有name的 列名key1是name
c 6
g1 5
t 3
Name: data1, dtype: int64
--------------------------------------------------------------------------------
如果是多分组:
group2 = df['data1'].groupby([ df['key1'], df['key2'] ])
grouped = df['data1'].groupby([['g1', 'g1', 't', 't', 't'],[1,2,1,1,1]])

多分组后获得的是一维的数据,不利于观察
key1 key2
a one 4
two 8
b one 4
two 2
Name: data1, dtype: int64

means = group2.mean()
means.unstack()
输出:
key2 one two
key1
a 4 8
b 4 2
--------------------------------------------------------------------------------
通常,分组信息就是要处理的DataFrame的某一列。这里,你还可以将列名(可以是字符串、
数字或其他Python对象)用作分组键,这样的操作会作用到所有的列上,但是有些列不是数字
这是那些俗称“麻烦列”的列就会被踢出计算结果,

# 按照 key1 分组计算平均值,key2列也要计算平均值,发现是麻烦列,结果没有他了,被踢了
df.groupby('key1').mean()
输出:
data1 data2
key1
a 5.333333 4.333333
b 3.000000 3.500000


# 多个分组依据
df.groupby(['key1', 'key2']).mean()


df.groupby(['key1', 'key2']).size() # 获取分组后样本点的数量
--------------------------------------------------------------------------------
对分组进行迭代
分组的时候是没有麻烦列的,没有数据被踢出,只是涉及到计算,有些列无法计算,这样的才会被踢出
--------------------------------------------------------------------------------
for name, group in df.groupby('key1'):
print(name)
print(group)
--------------------------------------------------------------------------------
dict(list(df.groupby('key1')))['a'] 把分组结果变成字典,并从中取出 a 键的值
--------------------------------------------------------------------------------
df.groupby('key1') 默认是把数据按照 key1 为依据,对行上分组。比如 前10条为一组,后10条另一组。
还能按列分组,比如1,2,5列是学生基本信息,必须填写的那种, 3,4,6 是扩展信息,可选填写
现在把列分组成2个,基本信息,扩展信息,
stu_df.groupby(['baseinfo', 'baseinfo', 'ext', 'ext','baseinfo', 'ext'], axis=1)
--------------------------------------------------------------------------------
还能按照数据类型分组,比如可计算的列为一组,不是数值类型的列为一组。
在df数据构造的时候,df会根据数据的实际情况给他们一个合适的数据类型,所以每列的数据类型都是一样的。

df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two','one'],
'data1' : [2,8,4,2,6],
'data2' : [1,7,4,3,5]})

输出:
key1 key2 data1 data2
0 a one 2 1
1 a two 8 7
2 b one 4 4
3 b two 2 3
4 a one 6 5

df.dtypes:
输出:
key1 object
key2 object
data1 int64
data2 int64
dtype: object

用数据类型分组,相同数据类型的为一组,这是就是列分组了, df.dtypes 每列数据类型组成的Series
g3 = df.groupby(df.dtypes, axis=1)
--------------------------------------------------------------------------------
选取一列或列的子集
--------------------------------------------------------------------------------
df.groupby('key1')['data1']
df.groupby('key1')[['data2']]
是以下代码的语法糖:
df['data1'].groupby(df['key1'])
df[['data2']].groupby(df['key1'])
--------------------------------------------------------------------------------
有些时候不是对整个 DF 进行分组计算,而是对其中的某一列或者多列进行统计计算。因此
需要选出某些需要的列进行分组计算即可,比如:
df.groupby(['key1', 'key2'])['data2']
--------------------------------------------------------------------------------
通过字典或Series进行分组
--------------------------------------------------------------------------------
上述的分组都是给一个数组,['a','a', 'b', 'b', 'c'] 长度必须和原数据长度一样,因为
他要按照位置一一对应,然后,根据数组中的数值是否相等判定是不是同一个组。

如果原数据的长度很长,比如是从数据库中查找出来的,60个学生的10000条数据,按照
学生分组,这时如果按照上面的分组方式就麻烦了,先弄出一个 10000 长度的数组,
然后还要按照顺序标明 第1条,第5条,第19条....是学生A, ...., 这只是举例,当然可以使用
原数据的学生姓名了作为分组依据。

所以可以字典映射,{'StuA':'A', 'StuB':'B' .... }, 字典是 60个学生和对应的值。groupby(字典) 即可

people = pd.DataFrame(np.arange(30).reshape(6,5),
columns=['a', 'b', 'c', 'd', 'e',],
index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis', 'lucy'])

people.iloc[2:3, [1,2]] = np.nan # 故意NA值
people 输出:
a b c d e
Joe 0 1.0 2.0 3 4
Steve 5 6.0 7.0 8 9
Wes 10 NaN NaN 13 14
Jim 15 16.0 17.0 18 19
Travis 20 21.0 22.0 23 24
lucy 25 26.0 27.0 28 29

mapping = {'a': 'red', 'b': 'red', 'c': 'blue','d': 'blue', 'e': 'red', 'f' : 'orange'}
by_column = people.groupby(mapping, axis=1)
by_column.sum()
输出: NA 值会直接忽略
blue red
Joe 5.0 5.0
Steve 15.0 20.0
Wes 13.0 24.0
Jim 35.0 50.0
Travis 45.0 65.0
lucy 55.0 80.0
--------------------------------------------------------------------------------
字典可以,Series 也可以
se = pd.Series(['red','red', 'blue','red', 'blue','white', 'green'], index=['a','b','c','d','e','f','g'])
by_column = people.groupby(se, axis=1)
by_column.sum()
--------------------------------------------------------------------------------
通过函数进行分组
--------------------------------------------------------------------------------
people.groupby(len).sum() # 按照名字的长度分组,名字长度一样的一组
输出:
a b c d e
3 25 17.0 19.0 34 37 <----名字长度是3个的统计结果
4 25 26.0 27.0 28 29
5 5 6.0 7.0 8 9
6 20 21.0 22.0 23 24

将函数跟数组、列表、字典、Series混合使用也不是问题,因为任何东西在内部都会被转换为数组
people.groupby([len, ['a', 'a', 'b', 'b', 'a', 'b']]).sum()
people.groupby([len, key_list]).min()
要求,传入的 list 还是要求和原数组的长度一致,而且按照位置一一映射。现在相当于
两个分组,现在按照名字的长度分组,然后按照本条数据对应list的值再分组
--------------------------------------------------------------------------------
columns = pd.MultiIndex.from_arrays([['US', 'US', 'US','JP', 'JP'],[1, 3, 5, 1, 3]], names=['gj', 'num'])
hier_df = pd.DataFrame(np.random.randn(4, 5), columns=columns)
输出:
gj US JP
num 1 3 5 1 3
0 -0.679403 0.224059 0.503013 -1.993131 0.590435
1 0.046812 -1.212013 -1.136789 0.204140 1.095048
2 -0.093172 0.958421 0.230009 -1.614276 1.689931
3 0.232094 0.942871 0.065289 0.544477 1.193635
--------------------------------------------------------------------------------
hier_df.groupby(level='gj', axis=1).count() # 使用原本的轴索引,指定轴索引 level 即可
hier_df.groupby(level=0, axis=1).count() # 索引如果没有指定名字,还能使用 0 1,表示第几级的索引
--------------------------------------------------------------------------------



>> 目录 << 


 

分享
收藏
点赞人
举报
文章标签
评论列表

推荐

暂无推荐