使用pandas.cut()并将其设置为数据帧的索引

时间:2017-08-16 19:23:38

标签: python pandas numpy matplotlib pandas-groupby

我正在尝试找到一种更简单的方法来使用我的数据框运行聚合函数,而不是手动提取数据并单独从数据框本身运行这些函数。我有一个团队的足球统计数据,我想根据年龄进行分析和统计。我想把这些年龄区分开来,然后根据这些年龄组运行统计数据。更具体地说,我有一个df:

df = pd.DataFrame({'Age':[20,30,22,27,35,33,22,28,29,21,28,33,29,27,31,20,25,26,31,33,29,18],
             'Goals':np.random.randint(1,6,22),
             'Shots on Goals':np.random.randint(5,20,22),
             'Yellow Cards':np.random.randint(1,6,22),
             'Assists':np.random.randint(0,16,22)})
df['Age Grps'] = pd.cut(df.Age, bins =[17,24,28,32,36])
df.set_index(['Age Grps'], inplace = True)
df.head(8)

其中输出以下数据框,并将索引设置为分箱年龄组:

| Age Grps | Age | Assists | Goals | Shot on Goals | Yellow Cards |
|----------|-----|---------|-------|---------------|--------------|
|  (17,24] |  20 |    3    |   3   |       13      |       2      |
| (28, 32] |  30 |    2    |   3   |       11      |       3      |
|  (17,24] |  22 |    10   |   3   |       14      |       5      |
|  (24,28] |  27 |    3    |   1   |       16      |       3      |
|  (32,36] |  35 |    1    |   4   |       5       |       1      |
|  (32,36] |  33 |    5    |   4   |       17      |       1      |
|  (17,24] |  22 |    14   |   5   |       13      |       3      |
|  (24,28] |  28 |    14   |   2   |       7       |       4      |

是否可以将当前索引(Age Grps)分组以产生以下结果:

╔══════════╦═════╦═════════╦═══════╦═══════════════╦══════════════╗
║ Age Grps ║ Age ║ Assists ║ Goals ║ Shot on Goals ║ Yellow Cards ║
╠══════════╬═════╬═════════╬═══════╬═══════════════╬══════════════╣
║  (17,24] ║  20 ║    3    ║   3   ║       13      ║       2      ║
║          ╠═════╬═════════╬═══════╬═══════════════╬══════════════╣
║          ║  22 ║    14   ║   5   ║       13      ║       3      ║
║          ╠═════╬═════════╬═══════╬═══════════════╬══════════════╣
║          ║  22 ║    10   ║   3   ║       14      ║       5      ║
╠══════════╬═════╬═════════╬═══════╬═══════════════╬══════════════╣
║  (24,28] ║  27 ║    3    ║   1   ║       16      ║       3      ║
║          ╠═════╬═════════╬═══════╬═══════════════╬══════════════╣
║          ║  28 ║    14   ║   2   ║       7       ║       4      ║
╠══════════╬═════╬═════════╬═══════╬═══════════════╬══════════════╣
║  (28,32] ║  28 ║    14   ║   2   ║       7       ║       4      ║
╠══════════╬═════╬═════════╬═══════╬═══════════════╬══════════════╣
║  (32,36] ║  35 ║    1    ║   4   ║       5       ║       1      ║
║          ╠═════╬═════════╬═══════╬═══════════════╬══════════════╣
║          ║  33 ║    5    ║   4   ║       17      ║       4      ║
╚══════════╩═════╩═════════╩═══════╩═══════════════╩══════════════╝

我希望能够做的是为每个年龄组运行汇总统计数据,例如每个年龄组的平均助攻数,平均目标数,平均目标投篮数等等。等等:

df['Average Goals'] = df.groupby('bucket')['Goals'].mean()
df['Average Assists'] = df.groupby('bucket')['Assists'].mean()

为了生成这样的表:

╔══════════╦═════╦═════════╦═════════════════╦═══════╦═══════════════╦═══════════════╦══════════════╗
║ Index    ║ Age ║ Assists ║ Average Assists ║ Goals ║ Average Goals ║ Shot on Goals ║ Yellow Cards ║
╠══════════╬═════╬═════════╬═════════════════╬═══════╬═══════════════╬═══════════════╬══════════════╣
║  (17,24] ║  20 ║    3    ║        9        ║   3   ║      3.67     ║       13      ║       2      ║
║          ╠═════╬═════════╣                 ╬═══════╬               ╬═══════════════╬══════════════╣
║          ║  22 ║    14   ║                 ║   5   ║               ║       13      ║       3      ║
║          ╠═════╬═════════╣                 ╬═══════╬               ╬═══════════════╬══════════════╣
║          ║  22 ║    10   ║                 ║   3   ║               ║       14      ║       5      ║
╠══════════╬═════╬═════════╬═════════════════╬═══════╬═══════════════╬═══════════════╬══════════════╣
║  (24,28] ║  27 ║    3    ║       8.5       ║   1   ║      1.5      ║       16      ║       3      ║
║          ╠═════╬═════════╣                 ╬═══════╬               ╬═══════════════╬══════════════╣
║          ║  28 ║    14   ║                 ║   2   ║               ║       7       ║       4      ║ 
╠══════════╬═════╬═════════╬═════════════════╬═══════╬═══════════════╬═══════════════╬══════════════╣
║  (28,32] ║  28 ║    14   ║        14       ║   2   ║       2       ║       7       ║       4      ║
╠══════════╬═════╬═════════╬═════════════════╬═══════╬═══════════════╬═══════════════╬══════════════╣
║  (32,36] ║  35 ║    1    ║        3        ║   4   ║       4       ║       5       ║       1      ║
║          ╠═════╬═════════╣                 ╬═══════╬               ╬═══════════════╬══════════════╣
║          ║  33 ║    5    ║                 ║   4   ║               ║       17      ║       4      ║
╚══════════╩═════╩═════════╩═════════════════╩═══════╩═══════════════╩═══════════════╩══════════════╝

我知道我可以以列表的形式提取数据并执行我需要的统计数据,但我正在尝试以“pandorable”的方式做事。此外,我将使用matplotlib绘制这些数据,我想使用pandas和matplotlib API df.plot()的简单方法。

提前感谢您的帮助

1 个答案:

答案 0 :(得分:1)

我认为如果原始df需要新列,则需要transform,但如果从列Age Grps设置索引,则会返回很多警告:

df['Age Grps'] = pd.cut(df.Age, bins =[17,24,28,32,36])
df = df.sort_values('Age Grps')
df['Average Goals'] = df.groupby('Age Grps')['Goals'].transform('mean')
df['Average Assists'] = df.groupby('Age Grps')['Assists'].transform('mean')

但如果需要汇总数据,请使用DataFrameGroupBy.agg

df1 = df.groupby(pd.cut(df.Age, bins =[17,24,28,32,36]))
        .agg({'Goals':'mean', 'Assists':'mean', 'Yellow Cards':'sum'})
print (df1)
          Yellow Cards    Assists     Goals
Age                                        
(17, 24]            12   8.000000  3.166667
(24, 28]            18   4.833333  1.833333
(28, 32]            21  11.333333  3.000000
(32, 36]            13  11.000000  2.250000