计算数据框系列中的唯一变化百分比

时间:2019-10-30 19:33:10

标签: python pandas dataframe

我正在尝试计算百分比变化的版本,其中公式为(b-a)/(b+a)(如果a和b均为0,则应该返回0)

我需要对数据框进行分组,对其进行排序,然后将此功能应用于每个组。

我遇到了与多索引相关的错误。

数据:

import random
import pandas as pd

random.seed(42)
group = [random.choice(['a', 'b', 'c', 'd', 'e']) for _ in range(300)]
group2 = [random.choice(['a', 'b', 'c', 'd', 'e']) for _ in range(300)]
x = [random.randint(1, 1000) for _ in range(300)]
number = [random.randint(1, 1000) for _ in range(300)]

df = pd.DataFrame({'group':group, 'group2':group2, 'number':number, 'x':x})
df.sort_values('number').groupby(['group', 'group2'])['x'].groups.keys()

# lets look at a specific group:
df.sort_values('number').groupby(['group', 'group2'])['x'].get_group(('a', 'a'))
206    349
1      226
114    965
48     771
228    662
157    471
128    701
201    500

我需要按两组分组,按数字排序,然后按

(b-a)/(a+b)

我尝试创建一种解决方案,该解决方案很笨拙,当应用于分组的数据框时,它并不能真正起作用。另一件事,我做了pd.concat()来创建数据帧,因为实际上分组的数据帧具有不同的索引时,索引返回为0+。我这样做是为了保留索引。我知道必须有更好的方法。

def relative_diff(x):
    df = pd.concat([x.shift(1), x], axis=1).assign(newcol=np.nan)
    for i, a, b in zip(range(len(df)), df.iloc[:,0], df.iloc[:,1]):
        if a == 0 and b == 0:
            df.iloc[i, 2] = 0
        else:
            df.iloc[i, 2] = ((b-a)/(b+a))
    return df.iloc[:,2]

当我将其应用于特定的群体时,我会得到我真正想要的东西:

example = df.sort_values('number').groupby(['group', 'group2'])['x'].get_group(('a', 'a'))

relative_diff(example)

206         NaN
1     -0.213913
114    0.620487
48    -0.111751
228   -0.076064
157   -0.168579
128    0.196246
201   -0.167361

我现在正在尝试将此功能.apply()应用于分组的数据框:

df.sort_values('number').groupby(['group', 'group2'])['x'].apply(relative_diff)

我收到cannot handle a non-unique multi-index!错误,并且被卡住了。

编辑:

查看WeNYoBen的答案后,它对于上述数据集非常适用,但是由于任何原因,当我查看第一组实际数据时,我看到:

144433    11
535075     6
725163     5
211134     3
89080      3
236916     1
593010     1
648680     2
56196      1
404572     2
724103     3
663501     7

它给我错误Buffer has wrong number of dimensions (expected 1, got 0)

2 个答案:

答案 0 :(得分:1)

我们可以做到

pd.concat([relative_diff(y) for x , y in df.sort_values('number').groupby(['group', 'group2'])['x']])

答案 1 :(得分:0)

IIUC,您只想先计算位移序列,然后即可执行正常操作:

df = df.sort_values('number')

shifted = df.groupby(['group', 'group2'])['x'].shift()
(shifted - df['x']).div(shifted + df['x']).fillna(0)

输出:

134    0.000000
7      0.050592
103    0.000000
204    0.000000
98     0.000000
         ...   
21     0.055165
229   -0.204819
185    0.372709
263    0.116757
110   -0.161116
Length: 300, dtype: float64