1

我正在尝试使用 Pandas 生成报告,按一组字段分组:

这就是我正在做的事情:

#!/usr/bin/env python3

import pandas as pd

data = [
    {
        'id': 1,
        'name': 'name1',
        'pretty_name': 'Pretty Name 1',
        'server_name': 'exampleserver.local',
        'provider': 'provider1',
        'type': 'A',
        'status': 'KO'
    },
    {
        'id': 2,
        'name': 'name2',
        'pretty_name': 'Pretty Name 2',
        'server_name': 'exampleserver1.local',
        'provider': 'provider2',
        'type': 'B',
        'status': 'OK'
    },
    {
        'id': 1,
        'name': 'name1',
        'pretty_name': 'Pretty Name 1',
        'server_name': 'exampleserver.local',
        'provider': 'provider1',
        'type': 'A',
        'status': 'KO'
    },
    {
        'id': 1,
        'name': 'name1',
        'pretty_name': 'Pretty Name 1',
        'server_name': 'exampleserver.local',
        'provider': 'provider1',
        'type': 'A',
        'status': 'OK'
    },
    {
        'id': 2,
        'name': 'name2',
        'pretty_name': 'Pretty Name 2',
        'server_name': 'exampleserver.local',
        'provider': 'provider2',
        'type': 'A',
        'status': 'OK'
    }
]

df = pd.DataFrame(data)

grouped = df.groupby(['server_name', 'provider', 'type', 'status'])['id'].count()
print(grouped.to_string())

返回:

server_name           provider   type  status
exampleserver.local   provider1  A     KO        2
                                       OK        1
                      provider2  A     OK        1
exampleserver1.local  provider2  B     OK        1

这没关系,但我想在结果中添加一行,其中包含每个提供者的总数。IE

server_name           provider   tot  type  status
exampleserver.local   provider1  3    A     KO        2
                                            OK        1
                      provider2  1    A     OK        1
exampleserver1.local  provider2  1    B     OK        1

我很确定用 Pandas 可以很容易地做到这一点,但是我花了几个小时阅读文档却没有运气。

任何指针?

谢谢。

编辑:我已经更正并扩展了这个例子,因为它并没有真正的意义。

4

1 回答 1

3

provider1如果与DataFrame.assignand匹配,您可以创建辅助列进行比较Series.eq,转换为整数,因此您可以sum用于计数匹配值:

grouped = (df.assign(new=df['provider'].str.contains('provider1').astype(int))
             .groupby(['server_name', 'provider', 'type', 'status'])['new']
             .agg([('count','size'), ('provider1_count','sum')])
             .reset_index())
print (grouped)
           server_name   provider type status  count  provider1_count
0  exampleserver.local  provider1    A     KO      1                1
1  exampleserver.local  provider2    A     OK      1                0
2  exampleserver.local  provider2    B     OK      1                0

编辑:

您可以添加as_index=FalseforDataFramerename列:

df1 = (df.groupby(['server_name', 'provider', 'type', 'status'], as_index=False)['id']
         .count()
         .rename(columns={'id':'counts'}))

2然后,如果要在位置上使用新列,请DataFrame.insert使用GroupBy.transform

df1.insert(2, 'tot', df1.groupby(['server_name','provider'])['counts'].transform('sum'))
print(df1)
            server_name   provider  tot type status  counts
0   exampleserver.local  provider1    3    A     KO       2
1   exampleserver.local  provider1    3    A     OK       1
2   exampleserver.local  provider2    1    A     OK       1
3  exampleserver1.local  provider2    1    B     OK       1

最后如果需要Multiindex使用DataFrame.set_index

grouped = df1.set_index(['server_name', 'provider', 'tot','type', 'status'])['counts']
print (grouped)
server_name           provider   tot  type  status
exampleserver.local   provider1  3    A     KO        2
                                            OK        1
                      provider2  1    A     OK        1
exampleserver1.local  provider2  1    B     OK        1
Name: counts, dtype: int64
于 2020-01-14T12:16:25.323 回答