用groupby计算条件中位数

时间:2019-08-22 18:25:53

标签: pandas

我正在尝试找出一种有效的方法(关于代码行数),同时使用group by语句来计算数据帧的条件中值。

下面是我的数据结构:

id     date    exp    d_x    yield
 1     2/5     3/10    .2     0.01
 1     2/5     3/10    .48    0.09
 1     2/5     3/10    .67    0.10
 1     2/5     3/10    .77    0.04
 1     2/5     4/15    .2     0.31
 1     2/5     4/15    .65    0.10
...    ...     ...     ..     ...
29     5/4     10/20   .24    0.21

我基本上想要的是: 新列-称为“ median_yield”,它是所有组的所有产量的中位数,d_x <.5。

grouping = (id, date, exp)

我尝试过的是以下内容:

df.query("d_x < .5").groupby(['id', 'date', 'Expiration'], as_index=False)['yield'].transform('median')

但是,结果很好,但是对于d_x> .5,结果是Nan。

所需的输出:

id     date    exp    d_x    yield   median_y
 1     2/5     3/10    .2     0.01    0.5
 1     2/5     3/10    .48    0.09    0.5
 1     2/5     3/10    .67    0.10    0.5
 1     2/5     3/10    .77    0.04    0.5
 1     2/5     4/15    .2     0.31    0.31
 1     2/5     4/15    .65    0.10    0.31
...    ...     ...     ..     ...     ....
29     5/4     10/20   .24    0.21    ....

示例: 数据框:

df1 = {'id' : [1, 1, 1, 1, 1, 2, 2, 2, 2, 2],
       'date' : ["2/5", "2/5", "2/5", "2/5", "2/5", "3/5", "3/5", "3/5", 
                 "3/5", "3/5"],
        'exp' : ["3/10", "3/10", "3/10", "3/10", "3/10", "4/15", "4/15", 
                 "4/15", "4/15", "4/15"],
        'd_x' : [.2, .431, .501, .56, .77, .10, .15, .61, .32, .91],
        'yield' : [.01, .04, .05, .10, .05, .012, .10, .20, .12, .05]}

df1 = pd.DataFrame(df1)

df1["median_y"] = df1.query("d_x < .5")\
                        .groupby(['id', 'date', 'exp'])\
                        ['yield'].transform('median')

所需的样本数据输出:

id     date    exp    d_x    yield   median_y
 1     2/5     3/10    .2     0.01    0.025
 1     2/5     3/10    .431   0.04    0.025
 1     2/5     3/10    .501   0.05    0.025
 1     2/5     3/10    .56    0.1     0.025
 1     2/5     3/10    .77    0.05    0.025
 2     3/5     4/15    .1     0.012   0.1
 2     3/5     4/15    .15    0.1     0.1
 2     3/5     4/15    .61    0.2     0.1
 2     3/5     4/15    .32    0.12    0.1
 2     3/5     4/15    .91    0.05    0.1

2 个答案:

答案 0 :(得分:2)

您可以这样做:

df1.query("d_x < .5").groupby(['id', 'date', 'exp'])['yield']\
    .agg('median').rename('median_y').reset_index().merge(df1)

使用transform而不是使用agg,然后使用merge返回到分组列上的原始数据框。

输出:

   id date   exp  median_y    d_x  yield
0   1  2/5  3/10     0.025  0.200  0.010
1   1  2/5  3/10     0.025  0.431  0.040
2   1  2/5  3/10     0.025  0.501  0.050
3   1  2/5  3/10     0.025  0.560  0.100
4   1  2/5  3/10     0.025  0.770  0.050
5   2  3/5  4/15     0.100  0.100  0.012
6   2  3/5  4/15     0.100  0.150  0.100
7   2  3/5  4/15     0.100  0.610  0.200
8   2  3/5  4/15     0.100  0.320  0.120
9   2  3/5  4/15     0.100  0.910  0.050

answer评论:

df1.merge(df1.query("d_x < .5").groupby(['id', 'date', 'exp'])['yield']\
   .agg('median').rename('median_y').reset_index())

输出:

   id date   exp    d_x  yield  median_y
0   1  2/5  3/10  0.200  0.010     0.025
1   1  2/5  3/10  0.431  0.040     0.025
2   1  2/5  3/10  0.501  0.050     0.025
3   1  2/5  3/10  0.560  0.100     0.025
4   1  2/5  3/10  0.770  0.050     0.025
5   2  3/5  4/15  0.100  0.012     0.100
6   2  3/5  4/15  0.150  0.100     0.100
7   2  3/5  4/15  0.610  0.200     0.100
8   2  3/5  4/15  0.320  0.120     0.100
9   2  3/5  4/15  0.910  0.050     0.100

答案 1 :(得分:2)

您可以稍微更改命令以获取所需的输出,如下所示。 (我不知道您编辑过添加新样本。在您的新样本上):

df1['median_y'] = (df1['yield'].where(df1.d_x < .5)
                              .groupby([df1.id, df1.date, df1.exp])
                              .transform('median'))


Out[232]:
   id date   exp    d_x  yield  median_y
0   1  2/5  3/10  0.200  0.010     0.025
1   1  2/5  3/10  0.431  0.040     0.025
2   1  2/5  3/10  0.501  0.050     0.025
3   1  2/5  3/10  0.560  0.100     0.025
4   1  2/5  3/10  0.770  0.050     0.025
5   2  3/5  4/15  0.100  0.012     0.100
6   2  3/5  4/15  0.150  0.100     0.100
7   2  3/5  4/15  0.610  0.200     0.100
8   2  3/5  4/15  0.320  0.120     0.100
9   2  3/5  4/15  0.910  0.050     0.100