@@ -110,27 +110,12 @@ def filter_column(self,
110110 column : Optional [str ],
111111 value_filter : Union [str , int , float , None ]) -> pd .DataFrame :
112112 """
113- Filter sensors by column and value_filter. If only column is passed, we
114- return rows that are not None. If the value_filter is passed, we only
115- return rows where the column matches that value.
113+ Returns the output of filter_column_to_array as a pandas dataframe.
116114 """
117115 # Check if there is no column passed
118116 if column is None :
119117 raise ValueError ('No column name provided to filter on!' )
120- out_l : List [dict ] = []
121- for sensor in self .all_sensors :
122- sensor_data = sensor .as_flat_dict (channel )
123- if column not in sensor_data :
124- raise ValueError (
125- f'Requested column { column } does not exist in sensor data!' )
126- result = sensor_data .get (column )
127- if value_filter and result != value_filter :
128- continue
129- if value_filter and result == value_filter :
130- out_l .append (sensor_data )
131- elif result is not None :
132- # If we do not want to filter the values, we filter out `None`s
133- out_l .append (sensor_data )
118+ out_l = filter_column_to_array (self .all_sensors , channel , column , value_filter )
134119
135120 if len (out_l ) == 0 :
136121 # pylint: disable=line-too-long
@@ -181,3 +166,63 @@ def to_dataframe(self,
181166
182167 sensor_data .index = sensor_data .pop ('id' )
183168 return sensor_data
169+
170+ def to_dataframe_multi_filter (self ,
171+ channel : str ,
172+ sensor_filters : Optional [str ] = None ,
173+ column : Optional [str ] = None ,
174+ value_filter : Union [str , int , float , None ] = None ) -> pd .DataFrame :
175+ """
176+ Returns a Pandas dataframe with filtered sensors, based on multiple filters
177+ provided by the user. If no filters are provided, we return all sensors in
178+ self.all_sensors.
179+ """
180+
181+ if not sensor_filters or len (sensor_filters ) == 0 or 'all' in sensor_filters :
182+ sensor_data = pd .DataFrame ([s .as_flat_dict (channel ) for s in self .all_sensors ])
183+ else :
184+ relevant_sensors = self .all_sensors
185+
186+ if 'outside' in sensor_filters :
187+ relevant_sensors = [s for s in relevant_sensors if s .location_type == 'outside' ]
188+ if 'useful' in sensor_filters :
189+ relevant_sensors = [s for s in relevant_sensors if s .is_useful ()]
190+ if 'family' in sensor_filters :
191+ relevant_sensors = [s for s in relevant_sensors if s .parent and s .child ]
192+ if 'no_child' in sensor_filters :
193+ relevant_sensors = [s for s in relevant_sensors if not s .child ]
194+
195+ if 'column' in sensor_filters :
196+ relevant_sensors = filter_column_to_array (
197+ relevant_sensors , channel , column , value_filter )
198+ else :
199+ relevant_sensors = [s .as_flat_dict (channel ) for s in relevant_sensors ]
200+ sensor_data = pd .DataFrame (relevant_sensors )
201+
202+ sensor_data .index = sensor_data .pop ('id' )
203+ return sensor_data
204+
205+ def filter_column_to_array (
206+ sensors , channel : str , column : Optional [str ],
207+ value_filter : Union [str , int , float , None ]
208+ ) -> List [dict ]:
209+ """
210+ Filter sensors by column and value_filter. If only column is passed, we
211+ return rows that are not None. If the value_filter is passed, we only
212+ return rows where the column matches that value.
213+ """
214+ out_l : List [dict ] = []
215+ for sensor in sensors :
216+ sensor_data = sensor .as_flat_dict (channel )
217+ if column not in sensor_data :
218+ raise ValueError (
219+ f'Requested column { column } does not exist in sensor data!' )
220+ result = sensor_data .get (column )
221+ if value_filter and result != value_filter :
222+ continue
223+ if value_filter and result == value_filter :
224+ out_l .append (sensor_data )
225+ elif result is not None :
226+ # If we do not want to filter the values, we filter out `None`s
227+ out_l .append (sensor_data )
228+ return out_l
0 commit comments