@@ -43,6 +43,7 @@ class Parameters(Enum):
4343 STREAM_FILTER_KEY2 = "stream_filter_key2"
4444 STREAM_FILTER_VALUE2 = "stream_filter_value2"
4545 KEEP_ONCE_PER_CASE = "keep_once_per_case"
46+ KEEP_NAN_VALUES = "keep_nan_values"
4647
4748
4849def apply_numeric_events (
@@ -66,6 +67,7 @@ def apply_numeric_events(
6667 Possible parameters of the algorithm:
6768 Parameters.ATTRIBUTE_KEY => indicates which attribute to filter
6869 positive => keep or remove events?
70+ Parameters.KEEP_NAN_VALUES -> Specifies if the filter should keep NAN values for the selected attribute. Default is False
6971
7072 Returns
7173 --------------
@@ -81,11 +83,19 @@ def apply_numeric_events(
8183 positive = exec_utils .get_param_value (
8284 Parameters .POSITIVE , parameters , True
8385 )
86+ keep_nan = exec_utils .get_param_value (
87+ Parameters .KEEP_NAN_VALUES , parameters , False
88+ )
8489
8590 if positive :
86- ret = df [ (df [attribute_key ] >= int1 ) & (df [attribute_key ] <= int2 )]
91+ event_filter = (df [attribute_key ] >= int1 ) & (df [attribute_key ] <= int2 )
8792 else :
88- ret = df [(df [attribute_key ] < int1 ) | (df [attribute_key ] > int2 )]
93+ event_filter = (df [attribute_key ] < int1 ) | (df [attribute_key ] > int2 )
94+
95+ if keep_nan :
96+ event_filter = event_filter | df [attribute_key ].isna ()
97+
98+ ret = df [event_filter ]
8999
90100 ret .attrs = copy (df .attrs ) if hasattr (df , "attrs" ) else {}
91101 return ret
@@ -112,6 +122,7 @@ def apply_numeric(
112122 Possible parameters of the algorithm:
113123 Parameters.ATTRIBUTE_KEY => indicates which attribute to filter
114124 Parameters.POSITIVE => keep or remove traces with such events?
125+ Parameters.KEEP_NAN_VALUES -> Specifies if the filter should keep NAN values for the selected attribute. Default is False
115126
116127 Returns
117128 --------------
@@ -130,6 +141,9 @@ def apply_numeric(
130141 positive = exec_utils .get_param_value (
131142 Parameters .POSITIVE , parameters , True
132143 )
144+ keep_nan = exec_utils .get_param_value (
145+ Parameters .KEEP_NAN_VALUES , parameters , False
146+ )
133147
134148 # stream_filter_key is helpful to filter on cases containing an event with an attribute
135149 # in the specified value set, but such events shall have an activity in
@@ -147,9 +161,11 @@ def apply_numeric(
147161 Parameters .STREAM_FILTER_VALUE2 , parameters , None
148162 )
149163
150- filtered_df_by_ev = df [
151- (df [attribute_key ] >= int1 ) & (df [attribute_key ] <= int2 )
152- ]
164+ event_filter = (df [attribute_key ] >= int1 ) & (df [attribute_key ] <= int2 )
165+ if keep_nan :
166+ event_filter = event_filter | df [attribute_key ].isna ()
167+ filtered_df_by_ev = df [event_filter ]
168+
153169 if stream_filter_key1 is not None :
154170 filtered_df_by_ev = filtered_df_by_ev [
155171 filtered_df_by_ev [stream_filter_key1 ] == stream_filter_value1
@@ -189,6 +205,8 @@ def apply_events(
189205 Parameters.ATTRIBUTE_KEY -> Attribute we want to filter
190206 Parameters.POSITIVE -> Specifies if the filter should be applied including traces (positive=True) or
191207 excluding traces (positive=False)
208+ Parameters.KEEP_NAN_VALUES -> Specifies if the filter should keep NAN values for the selected attribute. Default is False
209+
192210 Returns
193211 ----------
194212 df
@@ -203,11 +221,18 @@ def apply_events(
203221 positive = exec_utils .get_param_value (
204222 Parameters .POSITIVE , parameters , True
205223 )
224+ keep_nan = exec_utils .get_param_value (
225+ Parameters .KEEP_NAN_VALUES , parameters , False
226+ )
227+
228+ event_filter = df [attribute_key ].isin (values )
229+ if keep_nan :
230+ event_filter = event_filter | df [attribute_key ].isna ()
206231
207232 if positive :
208- ret = df [df [ attribute_key ]. isin ( values ) ]
233+ ret = df [event_filter ]
209234 else :
210- ret = df [~ df [ attribute_key ]. isin ( values ) ]
235+ ret = df [~ event_filter ]
211236
212237 ret .attrs = copy (df .attrs ) if hasattr (df , "attrs" ) else {}
213238 return ret
@@ -233,6 +258,8 @@ def apply(
233258 Parameters.ATTRIBUTE_KEY -> Attribute we want to filter
234259 Parameters.POSITIVE -> Specifies if the filter should be applied including traces (positive=True) or
235260 excluding traces (positive=False)
261+ Parameters.KEEP_NAN_VALUES -> Specifies if the filter should keep NAN values for the selected attribute. Default is False
262+
236263 Returns
237264 ----------
238265 df
@@ -250,13 +277,17 @@ def apply(
250277 positive = exec_utils .get_param_value (
251278 Parameters .POSITIVE , parameters , True
252279 )
280+ keep_nan = exec_utils .get_param_value (
281+ Parameters .KEEP_NAN_VALUES , parameters , False
282+ )
253283
254284 return filter_df_on_attribute_values (
255285 df ,
256286 values ,
257287 case_id_glue = case_id_glue ,
258288 attribute_key = attribute_key ,
259289 positive = positive ,
290+ keep_nan_values = keep_nan
260291 )
261292
262293
@@ -266,6 +297,7 @@ def filter_df_on_attribute_values(
266297 case_id_glue = "case:concept:name" ,
267298 attribute_key = "concept:name" ,
268299 positive = True ,
300+ keep_nan_values = False ,
269301):
270302 """
271303 Filter dataframe on attribute values
@@ -283,6 +315,8 @@ def filter_df_on_attribute_values(
283315 positive
284316 Specifies if the filtered should be applied including traces (positive=True) or excluding traces
285317 (positive=False)
318+ keep_nan_values
319+ Specifies if the filter should keep NAN values for the selected attribute
286320
287321 Returns
288322 ----------
@@ -291,7 +325,12 @@ def filter_df_on_attribute_values(
291325 """
292326 if values is None :
293327 values = []
294- filtered_df_by_ev = df [df [attribute_key ].isin (values )]
328+
329+ event_filter = df [attribute_key ].isin (values )
330+ if keep_nan_values :
331+ event_filter = event_filter | df [attribute_key ].isna ()
332+ filtered_df_by_ev = df [event_filter ]
333+
295334 i1 = df .set_index (case_id_glue ).index
296335 i2 = filtered_df_by_ev .set_index (case_id_glue ).index
297336 if positive :
0 commit comments