【问题标题】:Pandas - Sorting MultIndex by the Sum of SizesPandas - 按大小总和对 MultIndex 进行排序
【发布时间】:2018-09-25 06:29:05
【问题描述】:

我有一个代表用户对不同网站的请求的 Pandas DataFrame,DataFrame 中的每个实体都是一个请求。

为了简化问题,让它只有 2 列 - website 和 ip。

数据如下:

website.com 1.1.1.1
website.com 1.1.1.1
website.com 1.1.1.1
website.com 1.1.1.1
website.com 1.1.1.2

website1.com 1.1.1.1
website1.com 1.1.1.1
website1.com 1.1.1.3
website1.com 1.1.1.3

website2.com 1.1.1.4

我想对这个 DataFrame 进行分组,以便我可以看到按降序排列的点击率最高的网站,并在每个网站内看到访问它的 IP,也按降序排列。

我目前的解决方案是:

grouped_df = df.groupby(['website', 'IP'])
grouped_df.size()

这会给我:

website      IP         Size

website.com  1.1.1.1    4
             1.1.1.2    1
website1.com 1.1.1.1    2
             1.1.1.3    2
website2.com 1.1.1.4    1

我可以像 grouped_df.size().sort_values(ascending=False) 这样按大小对这个分组的 DataFrame 进行排序,但这将根据每个用户发出的请求数进行排序:

website      IP         Size

website.com  1.1.1.1    4    <---- sorted by size (N of requests from IP)
website1.com 1.1.1.1    2
             1.1.1.3    2
website.com  1.1.1.2    1
website2.com 1.1.1.4    1

而不是特定网站的请求总数:

website      IP         Size    Sum

website.com  1.1.1.1    4       5    <---- sorted by sum and sorted by size inside
             1.1.1.2    1
website1.com 1.1.1.1    2       4
             1.1.1.3    2
website2.com 1.1.1.4    1       1

我怎样才能做到这一点?

【问题讨论】:

  • @jpp 添加了一些最小数据示例和所需输出

标签: python pandas sorting multi-index


【解决方案1】:

用途:

df1 = df.groupby(['website', 'IP']).size().to_frame('Size')
df1['Sum'] = df1.groupby(level=0)['Size'].transform('sum')
#alternative solution
#df1['Sum'] = df1.reset_index()['website'].map(df1.sum(level=0).squeeze()).values
df1 = df1.sort_values(['Sum','Size'],ascending=False)

print (df1)
                      Size  Sum
website      IP                
website.com  1.1.1.1     4    5
             1.1.1.2     1    5
website1.com 1.1.1.1     2    4
             1.1.1.3     2    4
website2.com 1.1.1.4     1    1

解释:

  1. 首先聚合size 并将Series 通过Series.to_frame 转换为一列DataFrame
  2. 通过使用GroupBy.transform 和sum 或map 按sum 按第一级按第一级分组来创建新列Sum
  3. 最后sort_values

【讨论】:

    【解决方案2】:

    这是一种方式。想法是创建一个totals 列,然后在流程结束时按此列排序。

    res = df.groupby(['website', 'IP']).size().reset_index()
    
    s = df.groupby('website').size()
    res['totals'] = res['website'].map(s)
    
    res = res.sort_values('totals', ascending=False)
    
    print(res)
    
    #         website       IP  0  totals
    # 0   website.com  1.1.1.1  4       5
    # 1   website.com  1.1.1.2  1       5
    # 2  website1.com  1.1.1.1  2       4
    # 3  website1.com  1.1.1.3  2       4
    # 4  website2.com  1.1.1.4  1       1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-26
      • 2018-04-18
      • 2018-01-15
      • 2020-04-14
      • 2011-07-30
      • 2016-09-14
      • 2016-10-22
      相关资源
      最近更新 更多