def energy_per_dataframe(electricity, sample_period_multiplier=20, unit="kwh"): """pre-processes electricity and then gets total energy per channel, after masking out all gaps in mains. Returns ------- mains_total_energy, totals_per_appliance total_mains_energy : float totals_per_appliance : pd.Series each key is an ApplianceName each value is total energy """ # TODO: this might be an ugly hack to resolve circular dependencies. from nilmtk.preprocessing.electricity.building import mask_appliances_with_mains from nilmtk.preprocessing.electricity.single import insert_zeros # remove 'unmetered' and 'subpanels' from appliances electricity.appliances = electricity.remove_channels_from_appliances() # Sum split mains and DualSupply appliances electricity = electricity.sum_split_supplies() # TODO: Select common measurements. Maybe use electricity.select_common_measurements? # MEASUREMENT_PREFERENCES = [Measurement('power', 'active'), # Measurement('power', 'apparent')] # # Check if all channels share at least one Measurement (e.g. ('power', 'active')) # common_measurements = find_common_measurements(electricity) # common_measurement = None # for measurement_preference in MEASUREMENT_PREFERENCES: # if measurement_preference in common_measurements: # common_measurement = measurement_preference # print("Using common_measurement:", common_measurement) # break # if common_measurements is None and require_common_measurements: # raise NoCommonMeasurementError # Find large gaps in mains data and ignore those gaps for all appliance channels electricity = mask_appliances_with_mains(electricity, sample_period_multiplier) # Drop NaNs on all channels electricity = apply_func_to_values_of_dicts(electricity, lambda df: df.dropna(), ["appliances", "mains"]) # Insert_zeros on appliance data. print("Inserting zeros... may take a little while...", end="") sys.stdout.flush() single_insert_zeros = lambda df: insert_zeros(df, sample_period_multiplier=sample_period_multiplier) electricity = apply_func_to_values_of_dicts(electricity, single_insert_zeros, ["appliances", "mains"]) print("done inserting zeros") # Total energy used for mains total_mains_energy = get_total_energy_per_dict(electricity, "mains", unit) totals_per_appliance = {} for name, df in electricity.appliances.iteritems(): totals_per_appliance[name] = single.energy(df, unit=unit) return total_mains_energy, pd.Series(totals_per_appliance)
def fill_appliance_gaps(building, sample_period_multiplier=4): """Book-ends all large gaps with zeros using `nilmtk.preprocessing.electric.single.insert_zeros` on all appliances in `building` and then forward fills any remaining NaNs. This will result in forward-filling small gaps with the recorded value which precedes the gap, and forward-filling zeros in large gaps. NOTE: This function assumes that any gaps in the appliance data is the result of the appliance monitor and the appliance being off. Do not use this function if gaps in appliance data are the result of the IAM being broken (and hence the state of the appliance is unknown). Parameters ---------- building : nilmtk.Building sample_period_multiplier : float or int, optional The permissible maximum sample period expressed as a multiple of each dataframe's sample period. Any gap longer than the max sample period is assumed to imply that the IAM and appliance are off. If None then will default to 4 x the sample period of each dataframe. Returns ------- building_copy : nilmtk.Building See Also -------- nilmtk.preprocessing.electric.single.insert_zeros() """ # TODO: should probably remove any periods where all appliances # are not recording (which indicates that things are broken) # "book-end" each gap with a zero at each end single_insert_zeros = lambda df: single.insert_zeros( df, sample_period_multiplier=sample_period_multiplier) APPLIANCES = ['utility.electric.appliances'] new_building = apply_func_to_values_of_dicts(building, single_insert_zeros, APPLIANCES) # Now fill forward ffill = lambda df: pd.DataFrame.fillna(df, method='ffill') new_building = apply_func_to_values_of_dicts(new_building, ffill, APPLIANCES) return new_building