根据 pandas 中的条件减去行中的值

Subtract value in row based on condition in pandas

我需要根据故障计数的进展减去日期。 下面是具有两个输入列 DateFault_Count 的 table。我需要的输出列是 Option1Option2。最后两列显示日期差异计算。基本上当 Fault_Count 更改时,我需要计算从 Fault_Count 更改到故障计数初始开始的天数。例如 Fault_Count 在 1/4/2020 上更改为 2,我需要获取从 Fault_Count0 开始并更改为 2 的天数(即 1/4/2020 - 1/1/2020 = 3).

Date    Fault_Count Option1 Option2    Option1calc          Option2calc
1/1/2020       0       0        0       
1/2/2020       0       0        0       
1/3/2020       0       0        0       
1/4/2020       2       3        3   1/4/2020-1/1/2020    1/4/2020-1/1/2020
1/5/2020       2       0        0       
1/6/2020       2       0        0       
1/7/2020       4       3        3   1/7/2020-1/4/2020    1/7/2020-1/4/2020
1/8/2020       4       0        0       
1/9/2020       5       2        2   1/9/2020-1/7/2020    1/9/2020-1/7/2020
1/10/2020      5       0        0       
1/11/2020      0       2       -2   1/11/2020-1/9/2020   (1/11/2020-1/9/2020)*-1 as the fault resets
1/12/2020      1       1        1   1/12/2020-1/11/2020  1/12/2020-1/11/2020

下面是代码。

import pandas as pd

d = {'Date': ['1/1/2020', '1/2/2020', '1/3/2020', '1/4/2020', '1/5/2020', '1/6/2020', '1/7/2020', '1/8/2020', '1/9/2020', '1/10/2020', '1/11/2020', '1/12/2020'], 'Fault_Count' : [0, 0, 0, 2, 2, 2, 4, 4, 5, 5, 0, 1]}
df = pd.DataFrame(d)
df['Date'] = pd.to_datetime(df['Date'])
df['Fault_count_diff'] = df.Fault_Count.diff().fillna(0)
df['Cumlative_Sum'] = df.Fault_count_diff.cumsum()

我想我可以使用累积和和分组来获得组并获得组的第一个值的差异。这是我所能得到的,我还注意到使用累积总和并没有给我有序的组,因为一些 Fault_Count 被重置了。

    Date        Fault_Count   Fault_count_diff    Cumlative_Sum
0   2020-01-01       0               0.0                0.0
1   2020-01-02       0               0.0                0.0
2   2020-01-03       0               0.0                0.0
3   2020-01-04       2               2.0                2.0
4   2020-01-05       2               0.0                2.0
5   2020-01-06       2               0.0                2.0
6   2020-01-07       4               2.0                4.0
7   2020-01-08       4               0.0                4.0
8   2020-01-09       5               1.0                5.0
9   2020-01-10       5               0.0                5.0
10  2020-01-11       0              -5.0                0.0
11  2020-01-12       1               1.0                1.0

期望输出:

         Date  Fault_Count  Option1  Option2
0  2020-01-01            0      0.0      0.0
1  2020-01-02            0      0.0      0.0
2  2020-01-03            0      0.0      0.0
3  2020-01-04            2      3.0      3.0
4  2020-01-05            2      0.0      0.0
5  2020-01-06            2      0.0      0.0
6  2020-01-07            4      3.0      3.0
7  2020-01-08            4      0.0      0.0
8  2020-01-09            5      2.0      2.0
9  2020-01-10            5      0.0      0.0
10 2020-01-11            0      2.0     -2.0
11 2020-01-12            1      1.0      1.0

感谢您的帮助。

代替df['Fault_count_diff'] = ...和下一行,做:

df['cycle'] = (df.Fault_Count.diff() < 0).cumsum()

然后获取每次计数更改之间的日期。

选项1。如果 df 中存在所有日历日期:

ndays = df.groupby(['cycle', 'Fault_Count']).Date.size()

选项2。如果日期可能未显示在 df 中,而您仍想获取事件之间的日历天数:

ndays = df.groupby(['cycle', 'Fault_Count']).Date.min().diff().dropna()

使用:

m1 = df['Fault_Count'].ne(df['Fault_Count'].shift(fill_value=0))
m2 = df['Fault_Count'].eq(0) & df['Fault_Count'].shift(fill_value=0).ne(0)

s = df['Date'].groupby(m1.cumsum()).transform('first')

df['Option1'] = df['Date'].sub(s.shift()).dt.days.where(m1, 0)
df['Option2'] = df['Option1'].where(~m2, df['Option1'].mul(-1))

详情:

使用 Series.ne + Series.shift to create boolean mask m1 which represent the boundary condition when Fault_count changes, similarly use Series.eq + Series.shift and Series.ne 创建布尔掩码 m2 表示 Fault_count 重置的条件:

          m1           m2
0         False        False
1         False        False
2         False        False
3          True        False
4         False        False
5         False        False
6          True        False
7         False        False
8          True        False
9         False        False
10         True         True # --> Fault count reset
11         True        False

使用Series.groupby on consecutive fault counts obtained using m1.cumsum and transform the Date column using groupby.first:

print(s)
0    2020-01-01
1    2020-01-01
2    2020-01-01
3    2020-01-04
4    2020-01-04
5    2020-01-04
6    2020-01-07
7    2020-01-07
8    2020-01-09
9    2020-01-09
10   2020-01-11
11   2020-01-12
Name: Date, dtype: datetime64[ns]

使用Series.sub to subtract Date for s shifted using Series.shift and use Series.where根据掩码m2填充0并将其分配给Option1。类似地,我们根据掩码 m2:

Option1 获得 Option2
print(df)
         Date  Fault_Count  Option1  Option2
0  2020-01-01            0      0.0      0.0
1  2020-01-02            0      0.0      0.0
2  2020-01-03            0      0.0      0.0
3  2020-01-04            2      3.0      3.0
4  2020-01-05            2      0.0      0.0
5  2020-01-06            2      0.0      0.0
6  2020-01-07            4      3.0      3.0
7  2020-01-08            4      0.0      0.0
8  2020-01-09            5      2.0      2.0
9  2020-01-10            5      0.0      0.0
10 2020-01-11            0      2.0     -2.0
11 2020-01-12            1      1.0      1.0