03_7Pandas_分组运算

来源:互联网 发布:怎么用手机版淘宝开店 编辑:程序博客网 时间:2024/06/05 18:17

1.merge and transform

聚合运算改变了原始数据的shape。

但是如果我想保持原始数据的shape要咋办呢?

有两个方法:

  1. 使用merge的外连接,但着有点复杂
  2. 使用transform

于是我们来看以下这个例子:

# 导入需要的库import pandas as pdimport numpy as np
# 创建DataFramedict_obj = {'key1' : ['a', 'b', 'a', 'b',                       'a', 'b', 'a', 'a'],            'key2' : ['one', 'one', 'two', 'three',                      'two', 'two', 'one', 'three'],            'data1': np.random.randint(1, 10, 8),            'data2': np.random.randint(1, 10, 8)}df_obj = pd.DataFrame(dict_obj)print df_obj
   data1  data2 key1   key20      7      5    a    one1      4      5    b    one2      3      6    a    two3      4      4    b  three4      4      3    a    two5      3      3    b    two6      8      2    a    one7      8      2    a  three

创建完了DataFrame, 我们要来明确一下目标:按key1分组后,计算data1,data2的统计信息并附加到原始表格中

1.1 merge

要实现这个需求,如上所示,可以使用两个方法。先来看看第一个方法:merge

  1. 按照key1分组并且统计data1,data2后会生成一个新表
  2. 将生成的新表与原来的表格合并成一个表。

第一步很简单,如下,其中.add_prefix(‘sum_’)表示在原来的列标签前面加上前缀sum_

k1_sum = df_obj.groupby('key1').sum().add_prefix('sum_')print k1_sum
      sum_data1  sum_data2key1                      a            30         18b            11         12

现在我们来实现第二步,要将新表k1_sum附加回原始的表中。可以使用merge.

merge其实就等于join的操作,将两个表格根据某个相同的key连接起来,可以选择左连接,右连接,全连接,内连接。

print pd.merge(df_obj, k1_sum, left_on='key1', right_index=True)
   data1  data2 key1   key2  sum_data1  sum_data20      7      5    a    one         30         182      3      6    a    two         30         184      4      3    a    two         30         186      8      2    a    one         30         187      8      2    a  three         30         181      4      5    b    one         11         123      4      4    b  three         11         125      3      3    b    two         11         12

1.2 transform

transform的计算结果和原始数据的shape保持一直

# 使用transform计算k1_sum_tf = df_obj.groupby('key1').transform(np.sum).add_prefix('sum_')# 将transform的计算结果作为一个新列添加到原数据中df_obj[k1_sum_tf.columns] = k1_sum_tfprint df_obj
   data1  data2 key1   key2  sum_data1  sum_data2 sum_key20      7      5    a    one          7          5      one1      4      5    b    one          4          5      one2      3      6    a    two          3          6      two3      4      4    b  three          4          4    three4      4      3    a    two          4          3      two5      3      3    b    two          3          3      two6      8      2    a    one          8          2      one7      8      2    a  three          8          2    three

transform也可以传入自定义函数

# 自定义函数传入transformdef diff_mean(s):    """        返回数据与均值的差值    """    return s - s.mean()print df_obj.groupby('key1').transform(diff_mean)
      data1  data2  sum_data1  sum_data20  1.000000    1.4   1.000000        1.41  0.333333    1.0   0.333333        1.02 -3.000000    2.4  -3.000000        2.43  0.333333    0.0   0.333333        0.04 -2.000000   -0.6  -2.000000       -0.65 -0.666667   -1.0  -0.666667       -1.06  2.000000   -1.6   2.000000       -1.67  2.000000   -1.6   2.000000       -1.6

2. apply

grouped.apply(func)

func函数在各分组上调用,然后结果通过pd.concat组装到一起。

结果中会产生层级索引,外层索引是分组名,内层索引是df.obj的行索引。

# 从外部的csv文件读入数据dataset_path = './starcraft.csv'df_data = pd.read_csv(dataset_path, usecols=['LeagueIndex', 'Age', 'HoursPerWeek',                                              'TotalHours', 'APM'])
def top_n(df, n=3, column='APM'):    """        返回每个分组按 column 的 top n 数据    """    return df.sort_values(by=column, ascending=False)[:n]print df_data.groupby('LeagueIndex').apply(top_n)
                  LeagueIndex   Age  HoursPerWeek  TotalHours       APMLeagueIndex                                                            1           2214            1  20.0          12.0       730.0  172.9530            2246            1  27.0           8.0       250.0  141.6282            1753            1  20.0          28.0       100.0  139.63622           3062            2  20.0           6.0       100.0  179.6250            3229            2  16.0          24.0       110.0  156.7380            1520            2  29.0           6.0       250.0  151.64703           1557            3  22.0           6.0       200.0  226.6554            484             3  19.0          42.0       450.0  220.0692            2883            3  16.0           8.0       800.0  208.95004           2688            4  26.0          24.0       990.0  249.0210            1759            4  16.0           6.0        75.0  229.9122            2637            4  23.0          24.0       650.0  227.22725           3277            5  18.0          16.0       950.0  372.6426            93              5  17.0          36.0       720.0  335.4990            202             5  37.0          14.0       800.0  327.72186           734             6  16.0          28.0       730.0  389.8314            2746            6  16.0          28.0      4000.0  350.4114            1810            6  21.0          14.0       730.0  323.25067           3127            7  23.0          42.0      2000.0  298.7952            104             7  21.0          24.0      1000.0  286.4538            1654            7  18.0          98.0       700.0  236.03168           3393            8   NaN           NaN         NaN  375.8664            3373            8   NaN           NaN         NaN  364.8504            3372            8   NaN           NaN         NaN  355.3518
# apply函数接收的参数会传入自定义的函数中print df_data.groupby('LeagueIndex').apply(top_n, n=2, column='Age')
                  LeagueIndex   Age  HoursPerWeek  TotalHours       APMLeagueIndex                                                            1           3146            1  40.0          12.0       150.0   38.5590            3040            1  39.0          10.0       500.0   29.87642           920             2  43.0          10.0       730.0   86.0586            2437            2  41.0           4.0       200.0   54.21663           1258            3  41.0          14.0       800.0   77.6472            2972            3  40.0          10.0       500.0   60.59704           1696            4  44.0           6.0       500.0   89.5266            1729            4  39.0           8.0       500.0   86.72465           202             5  37.0          14.0       800.0  327.7218            2745            5  37.0          18.0      1000.0  123.40986           3069            6  31.0           8.0       800.0  133.1790            2706            6  31.0           8.0       700.0   66.99187           2813            7  26.0          36.0      1300.0  188.5512            1992            7  26.0          24.0      1000.0  219.66908           3340            8   NaN           NaN         NaN  189.7404            3341            8   NaN           NaN         NaN  287.8128

3. 禁止分组

group_keys=False

用于禁止层级索引

print df_data.groupby('LeagueIndex', group_keys=False).apply(top_n)
      LeagueIndex   Age  HoursPerWeek  TotalHours       APM2214            1  20.0          12.0       730.0  172.95302246            1  27.0           8.0       250.0  141.62821753            1  20.0          28.0       100.0  139.63623062            2  20.0           6.0       100.0  179.62503229            2  16.0          24.0       110.0  156.73801520            2  29.0           6.0       250.0  151.64701557            3  22.0           6.0       200.0  226.6554484             3  19.0          42.0       450.0  220.06922883            3  16.0           8.0       800.0  208.95002688            4  26.0          24.0       990.0  249.02101759            4  16.0           6.0        75.0  229.91222637            4  23.0          24.0       650.0  227.22723277            5  18.0          16.0       950.0  372.642693              5  17.0          36.0       720.0  335.4990202             5  37.0          14.0       800.0  327.7218734             6  16.0          28.0       730.0  389.83142746            6  16.0          28.0      4000.0  350.41141810            6  21.0          14.0       730.0  323.25063127            7  23.0          42.0      2000.0  298.7952104             7  21.0          24.0      1000.0  286.45381654            7  18.0          98.0       700.0  236.03163393            8   NaN           NaN         NaN  375.86643373            8   NaN           NaN         NaN  364.85043372            8   NaN           NaN         NaN  355.3518

注:部分例子来自于小象学院Robin课程

0 0
原创粉丝点击