I have a pandas dataframe df:
| Car | Open | Time |
|---|---|---|
| Audi A5 | 0 | 0 |
| Audi A5 | 0 | 1 |
| Audi A5 | 0 | 2 |
| Audi A5 | 1 | 3 |
| Audi A5 | 1 | 4 |
| Audi A5 | 0 | 5 |
| Audi A5 | 0 | 6 |
| Audi A5 | 0 | 7 |
| Audi A5 | 1 | 8 |
| Audi A5 | 1 | 9 |
| Mercedes Class A | 1 | 0 |
| Mercedes Class A | 1 | 1 |
| Mercedes Class A | 1 | 2 |
| Mercedes Class A | 0 | 3 |
| Mercedes Class A | 0 | 4 |
| Mercedes Class A | 1 | 5 |
| Mercedes Class A | 1 | 6 |
| Mercedes Class A | 0 | 7 |
| Mercedes Class A | 0 | 8 |
| Mercedes Class A | 1 | 9 |
I want to enlarge the active part of the binary series Open by n units, but after grouping the dataframe by Car.
An active part is a group of consecutive 1 that is either surrounded by 0, or having only 0 as previous value, or having only 0 as next values. The case when the series has only 1 as value is ignored.
If n = 1, I want to get the following dataframe :
| Car | Open | Time |
|---|---|---|
| Audi A5 | 0 | 0 |
| Audi A5 | 0 | 1 |
| Audi A5 | 1 | 2 |
| Audi A5 | 1 | 3 |
| Audi A5 | 1 | 4 |
| Audi A5 | 0 | 5 |
| Audi A5 | 0 | 6 |
| Audi A5 | 1 | 7 |
| Audi A5 | 1 | 8 |
| Audi A5 | 1 | 9 |
| Mercedes Class A | 1 | 0 |
| Mercedes Class A | 1 | 1 |
| Mercedes Class A | 1 | 2 |
| Mercedes Class A | 0 | 3 |
| Mercedes Class A | 1 | 4 |
| Mercedes Class A | 1 | 5 |
| Mercedes Class A | 1 | 6 |
| Mercedes Class A | 0 | 7 |
| Mercedes Class A | 1 | 8 |
| Mercedes Class A | 1 | 9 |
I can get the index of all active parts using the following code :
df = pd.DataFrame(
{
"Car": ["Audi A5"]*10 + ["Mercedes Class A"]*10,
"Time" : list(range(10)) + list(range(10)),
"Open" : [0,0,0,1,1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,1]
}
)
def enlarge(dataframe : pd.DataFrame, sensor : str, n : int = 1) -> pd.DataFrame:
get_group_indexes = (
lambda x: x.index[0]
if x.index[-1] - x.index[0] >= 1
else None
)
groups = (
dataframe[sensor]
.eq(0)
.cumsum()[dataframe[sensor].ne(0)]
.to_frame()
.groupby(sensor)
.apply(get_group_indexes)
.dropna()
)
if groups.empty:
return dataframe
for index in groups:
dataframe.loc[index-n:index, sensor] = 1
return dataframe
It works when I don't have to group by Car but I want to group by this column before perfoming this transformation. Does someone hqs an idea how to achieve this efficiently using pandas tricks ? Thanks.