使用应用于groupby的函数的结果以在原始df上进行计算

时间:2018-11-01 16:47:19

标签: python pandas numpy group-by

我有一些数据,如下df所示。 我正在尝试首先使用函数mean_angle计算每个组的平均角度。然后,使用函数fun将计算出的平均角度用于每组的另一次计算。

import pandas as pd
import numpy as np

生成示例数据

a = np.array([1,2,3,4]).repeat(4)
x1 = 90 + np.random.randint(-15, 15, size=a.size//2 - 2 )
x2 = 270 + np.random.randint(-50, 50, size=a.size//2 + 2 )

b = np.concatenate((x1, x2))
np.random.shuffle(b) 

df = pd.DataFrame({'a':a, 'b':b})

返回的数据框打印在下面。

    a   b
0   1   295
1   1   78
2   1   280
3   1   94
4   2   308
5   2   227
6   2   96
7   2   299
8   3   248
9   3   288
10  3   81
11  3   78
12  4   103
13  4   265
14  4   309
15  4   229

我的功能是mean_anglefun

def mean_angle(deg):

    deg = np.deg2rad(deg)

    deg = deg[~np.isnan(deg)]

    S = np.sum(np.sin(deg))
    C = np.sum(np.cos(deg))
    mu = np.arctan2(S,C)
    mu = np.rad2deg(mu)

    if mu <0:
        mu = 360 + mu

    return mu

def fun(x, mu):

    return  np.where(abs(mu - x) < 45, x, np.where(x+180<360, x+180, x-180))

我尝试过的

mu = df.groupby(['a'])['b'].apply(mean_angle)

df2 = df.groupby(['a'])['b'].apply(fun, args = (mu,)) #this function should be element wise

我知道这是完全错误的,但是我无法提出更好的方法。

所需的输出是这样的 ,其中mu每组的均值角

 a   b   c
0   1   295 np.where(abs(mu - 295) < 45, 295, np.where(295 +180<360, 295 +180, 295 -180))
1   1   78 np.where(abs(mu - 78) < 45, 78, np.where(78 +180<360, 78 +180, 78 -180))
2   1   280 np.where(abs(mu - 280  < 45, 280, np.where(280  +180<360, 280  +180, 280  -180))
3   1   94                ...
4   2   308               ...
5   2   227                .
6   2   96                 .
7   2   299                .
8   3   248                .
9   3   288                .
10  3   81                 .
11  3   78                 .
12  4   103                .
13  4   265                .
14  4   309                .
15  4   229                .

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

您不需要第二个函数,只需将必要的列传递给np.where()。因此,以相同的方式创建数据框而不修改您的mean_angle函数,我们有以下示例数据框:

    a    b
0   1  228
1   1  291
2   1   84
3   1  226
4   2  266
5   2  311
6   2   82
7   2  274
8   3   79
9   3  250
10  3  222
11  3   88
12  4   80
13  4  291
14  4  100
15  4  293

然后使用cmu创建groupby()列(包含您的transform()值),最后应用np.where()逻辑:

df['c'] = df.groupby(['a'])['b'].transform(mean_angle)
df['c'] = np.where(abs(df['c'] - df['b']) < 45, df['b'], np.where(df['b']+180<360, df['b']+180, df['b']-180))

收益:

    a    b    c
0   1  228  228
1   1  291  111
2   1   84  264
3   1  226  226
4   2  266  266
5   2  311  311
6   2   82  262
7   2  274  274
8   3   79  259
9   3  250   70
10  3  222   42
11  3   88  268
12  4   80  260
13  4  291  111
14  4  100  280
15  4  293  113