熊猫:在熊猫中复制一个Excel公式

时间:2020-10-14 22:24:26

标签: python pandas dataframe sorting

我有一个像这样的数据框:

   total_sum  pid
   5          2
   1          2
   6          7
   3          7
   1          7
   1          7
   0          7
   5         10
   1         10
   1         10

我想要的是另一列pos,例如:

   total_sum  pid    pos
   5          2      1
   1          2      2 
   6          7      1
   3          7      2
   1          7      3
   1          7      3
   0          7      4
   5         10      1
   1         10      2
   1         10      2

背后的逻辑是:

pos的初始pid值为1

如果pid不变,但total_sum改变,则pos的值增加1(例如前两行),否则pos的值就是前一个值(例如最后两行)。

我尝试过的事情:

 df['pos'] = 1
 df['pos'] = np.where(((df.pid.diff(-1)) == 0 & (df.total_sum.diff(-1) == 0)),
                                                     df.pos, (np.where(df.total_sum.diff(1) < 1, df.pos + 1, df.pos )))

当前,我在excel工作表中进行此操作,首先在pos的第一列中手动编写1,然后在pos的第二个单元格中编写公式:

=IF(A3<>A2,1,IF(B3=B2,C2,C2+1))

1 个答案:

答案 0 :(得分:3)

说明

groupby进行pid,将相同的pid分为不同的组。在每个组上,执行以下操作:

_在每个组上致电diffdiff返回整数,或者NaN表示2个连续行之间的差。每个组的第一行没有上一行,因此diff总是为每个组的第一行返回NaN

df.groupby('pid').total_sum.transform(lambda x: x.diff()

Out[120]:
0    NaN
1   -4.0
2    NaN
3   -3.0
4   -2.0
5    0.0
6   -1.0
7    NaN
8   -4.0
9    0.0
Name: total_sum, dtype: float64

_ ne检查是否有任何值不是0。它返回True而不返回0

df.groupby('pid').total_sum.transform(lambda x: x.diff().ne(0))

Out[121]:
0     True
1     True
2     True
3     True
4     True
5    False
6     True
7     True
8     True
9    False
Name: total_sum, dtype: bool

_ cumsum是连续累加每行的累加和。在Python中,True被解释为1,而False被解释为0。每个组的第一个始终为True,因此cumsum总是从1开始并将每行加起来以获得所需的输出。

df.groupby('pid').total_sum.transform(lambda x: x.diff().ne(0).cumsum())

Out[122]:
0    1
1    2
2    1
3    2
4    3
5    3
6    4
7    1
8    2
9    2
Name: total_sum, dtype: int32

将所有命令绑定到一个代码行,如下所示:

df['pos'] = df.groupby('pid').total_sum.transform(lambda x: x.diff().ne(0).cumsum())

Out[99]:
   total_sum  pid  pos
0          5    2    1
1          1    2    2
2          6    7    1
3          3    7    2
4          1    7    3
5          1    7    3
6          0    7    4
7          5   10    1
8          1   10    2
9          1   10    2