《利用python进行数据分析》读书笔记之高阶GroupBy应用

本文中可能使用的数据集来自:《利用python进行数据分析》数据集

之前我们已经讲过通过使用groupby方法来进行数据的分组和聚合。这里介绍一些可能会在数据分析过程中用到的额外用法。

分组转换和“展开”GroupBy

我们在之前分组和聚合的学习中知道,apply方法可以用于执行转换操作。transform方法与apply方法类似,但是会对你使用的函数进行更多的限制:

  • transform可以产生一个标量值,并广播到各分组的尺寸数据中
  • transform可以产生一个与输入分组尺寸相同的对象
  • transform不可以改变它的输入

为了更加直观的说明,首先考虑下面这个DataFrame:

df = pd.DataFrame({"key":list("abc") * 4,
                   "value":np.arange(12.)})
print(df)
#    key  value
# 0    a    0.0
# 1    b    1.0
# 2    c    2.0
# 3    a    3.0
# 4    b    4.0
# 5    c    5.0
# 6    a    6.0
# 7    b    7.0
# 8    c    8.0
# 9    a    9.0
# 10   b   10.0
# 11   c   11.0

现在我们想要计算key相同的数据的value的平均值,从之前数据聚合的知识可以知道,可以使用下面的方法:

g = df.groupby("key").value
print(g.mean())
# key
# a    4.5
# b    5.5
# c    6.5
# Name: value, dtype: float64

现在假设我们想要保持计算完平均值后返回的Series大小与原Series大小一样,每个位置上填充的是计算出的平均值,那么我们就可以使用transform方法:

print(g.transform(lambda x:x.mean()))
# 0     4.5
# 1     5.5
# 2     6.5
# 3     4.5
# 4     5.5
# 5     6.5
# 6     4.5
# 7     5.5
# 8     6.5
# 9     4.5
# 10    5.5
# 11    6.5
# Name: value, dtype: float64

当然,就像apply方法一样,还可以这样:

print(g.transform(np.mean))
print(g.transform('mean'))

再比如说,我们想进行一个组内的排序(序号a的数据一同排序,序号为b的一同排序……):

print(g.transform(lambda x:x.rank(ascending=False)))
# 0     4.0
# 1     4.0
# 2     4.0
# 3     3.0
# 4     3.0
# 5     3.0
# 6     2.0
# 7     2.0
# 8     2.0
# 9     1.0
# 10    1.0
# 11    1.0
# Name: value, dtype: float64

这里需要注意的是,使用内建的聚合函数如’mean’或者’sum’,通常会比apply函数更快。将这些函数传入transform方法可以进行一个分组展开的操作(正如之前看到的,将‘mean’传入transform)。

分组的时间重新采样

resample方法可以看做是在时间上的分组操作(resample的用法)。下面是一个小示例:

N = 15
times = pd.date_range("2017-5-20 00:00",freq="min",periods=N)
df = pd.DataFrame({"time":times,"value":np.arange(N)})
print(df.head())
#                  time  value
# 0 2017-05-20 00:00:00      0
# 1 2017-05-20 00:01:00      1
# 2 2017-05-20 00:02:00      2
# 3 2017-05-20 00:03:00      3
# 4 2017-05-20 00:04:00      4

之后我们可以按“time”进行索引,重新采样:

res = df.set_index("time").resample("5min").count()
print(res)
#                      value
# time                      
# 2017-05-20 00:00:00      5
# 2017-05-20 00:05:00      5
# 2017-05-20 00:10:00      5

现在考虑下面这个DataFrame对象,它包含着重复的时间项:

N = 15
times = pd.date_range("2017-5-20 00:00",freq="min",periods=N)
df2 = pd.DataFrame({"time":times.repeat(3),
                   "key":np.tile(list('abc'),N),
                    "value":np.arange(N * 3)})
print(df2.head(5))
#                  time key  value
# 0 2017-05-20 00:00:00   a      0
# 1 2017-05-20 00:00:00   b      1
# 2 2017-05-20 00:00:00   c      2
# 3 2017-05-20 00:01:00   a      3
# 4 2017-05-20 00:01:00   b      4

如果我们想按照key和time同时进行分组,那么我们就不能直接使用resample方法了,但是我们可以仍可以使用groupby方法:

time_key = pd.Grouper(freq = "5min")
#使用groupby方法按时间频率进行聚合的时候,需要传入Grouper对象(原书中为TimeGrouper对象)
resampled = df2.set_index("time")\
    .groupby(["key",time_key])\
    .sum()
#使用key和time_key进行分组,之后用sum方法进行聚合
print(resampled)
#                          value
# key time
# a   2017-05-20 00:00:00     30
#     2017-05-20 00:05:00    105
#     2017-05-20 00:10:00    180
# b   2017-05-20 00:00:00     35
#     2017-05-20 00:05:00    110
#     2017-05-20 00:10:00    185
# c   2017-05-20 00:00:00     40
#     2017-05-20 00:05:00    115
#     2017-05-20 00:10:00    190
print(resampled.reset_index())
#   key                time  value
# 0   a 2017-05-20 00:00:00     30
# 1   a 2017-05-20 00:05:00    105
# 2   a 2017-05-20 00:10:00    180
# 3   b 2017-05-20 00:00:00     35
# 4   b 2017-05-20 00:05:00    110
# 5   b 2017-05-20 00:10:00    185
# 6   c 2017-05-20 00:00:00     40
# 7   c 2017-05-20 00:05:00    115
# 8   c 2017-05-20 00:10:00    190
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值