根据 pandas 中的条件减去行中的值
Subtract value in row based on condition in pandas
我需要根据故障计数的进展减去日期。
下面是具有两个输入列 Date
和 Fault_Count
的 table。我需要的输出列是 Option1
和 Option2
。最后两列显示日期差异计算。基本上当 Fault_Count 更改时,我需要计算从 Fault_Count 更改到故障计数初始开始的天数。例如 Fault_Count 在 1/4/2020
上更改为 2,我需要获取从 Fault_Count
从 0
开始并更改为 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
我需要根据故障计数的进展减去日期。
下面是具有两个输入列 Date
和 Fault_Count
的 table。我需要的输出列是 Option1
和 Option2
。最后两列显示日期差异计算。基本上当 Fault_Count 更改时,我需要计算从 Fault_Count 更改到故障计数初始开始的天数。例如 Fault_Count 在 1/4/2020
上更改为 2,我需要获取从 Fault_Count
从 0
开始并更改为 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