I am trying to get the latest date at which a value was not null on a rolling time window, by group. It works pretty well without groups but it seems that the grouping shuffles everything.
Here is reproducible example:
import pandas as pd
from datetime import datetime as dt
import numpy as np
df = pd.DataFrame({})
df["date"] = [dt(2020, 10, i+1) for i in range(10)]
df["group"] = ["a" if int(i/3) == (i/3) else "b" for i in range(10)]
df["value"] = [i if int(i/2) == (i/2) else np.nan for i in range(10)]
dataframe
date group value
0 2020-10-01 a 0.0
1 2020-10-02 b NaN
2 2020-10-03 b 2.0
3 2020-10-04 a NaN
4 2020-10-05 b 4.0
5 2020-10-06 b NaN
6 2020-10-07 a 6.0
7 2020-10-08 b NaN
8 2020-10-09 b 8.0
9 2020-10-10 a NaN
Targeted output:
date group value output
0 2020-10-01 a 0.0 2020-10-01
1 2020-10-02 b NaN NaT
2 2020-10-03 b 2.0 2020-10-03
3 2020-10-04 a NaN 2020-10-01
4 2020-10-05 b 4.0 2020-10-05
5 2020-10-06 b NaN 2020-10-05
6 2020-10-07 a 6.0 2020-10-07
7 2020-10-08 b NaN 2020-10-05
8 2020-10-09 b 8.0 2020-10-09
9 2020-10-10 a NaN 2020-10-07
My attempt:
df = df.set_index("date").sort_index(ascending = True)
def latest_non_null_value_index(x):
y = x[np.isnan(x) == False]
print(y.index)
if len(y) > 0:
return y.index[-1]
else:
return np.nan
latest_index = df\
.groupby(["group"])\
.rolling("35D")\
["value"]\
.apply(lambda x: latest_non_null_value_index(x).timestamp())\
.reset_index()
def to_datetime_from_timestamp(x):
if pd.isnull(x) == False:
return dt.fromtimestamp(x)
else:
return pd.NaT
latest_index["value"] = latest_index["value"]\
.apply(to_datetime_from_timestamp)
What I get:
group date value
0 a 2020-10-01 2020-10-01 02:00:00
1 a 2020-10-04 2020-10-01 02:00:00
2 a 2020-10-07 2020-10-03 02:00:00
3 a 2020-10-10 2020-10-03 02:00:00
4 b 2020-10-02 NaT
5 b 2020-10-03 2020-10-06 02:00:00
6 b 2020-10-05 2020-10-07 02:00:00
7 b 2020-10-06 2020-10-07 02:00:00
8 b 2020-10-08 2020-10-07 02:00:00
9 b 2020-10-09 2020-10-10 02:00:00
Any idea what I have missed here?
EDIT: also it seems that I don't have this problem when taking the latest value... It really has to do with index.
EDIT2: also if I could somehow apply a function to 2 columns, I could have the date as a second column and get a workaround