Python 计算数据帧系列groupby中的唯一百分比更改

Python 计算数据帧系列groupby中的唯一百分比更改,python,pandas,dataframe,Python,Pandas,Dataframe,我试图计算百分比变化的一个版本,公式是(b-a)/(b+a)(如果a和b都是0,那么它应该返回0) 我需要按数据帧分组、排序,然后将此函数应用于每个组 我遇到了与多索引相关的错误 数据: 我需要按两组分组,按数字排序,然后我想按 (b-a)/(a+b) 我曾尝试创建一个解决方案,该解决方案很粗糙,在应用于分组数据帧时实际上不起作用。还有一件事,我做了pd.concat()。我这样做是为了保留索引。我知道一定有更好的办法 def relative_diff(x): df = pd.conc

我试图计算百分比变化的一个版本,公式是
(b-a)/(b+a)
(如果a和b都是0,那么它应该返回0)

我需要按数据帧分组、排序,然后将此函数应用于每个组

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

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

(b-a)/(a+b)

我曾尝试创建一个解决方案,该解决方案很粗糙,在应用于分组数据帧时实际上不起作用。还有一件事,我做了
pd.concat()。我这样做是为了保留索引。我知道一定有更好的办法

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)
我得到
无法处理非唯一的多索引错误,我被卡住了

编辑:

在回顾了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
它给我的错误
缓冲区有错误的维数(预期为1,得到0)
我们可以做

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

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

太好了,谢谢你。我现在遇到了另一个错误,我不能用当前的数据集准确地重现它,我不知道为什么<代码>缓冲区的维度数错误(预期为1,实际为0)
添加到中的注释中post@MattW. 在原始数据帧中是否有dup列名称?我没有。我设置了(计数器(data.columns.values())
,结果只有1。马特也把它们都看了一遍。我不知道为什么这适用于您的测试样本数据,但不适用于真实数据。。。
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