I have two pandas DataFrames, dfb
and dfv
, where dfb
has a higher sampling rate than dfv
. I want to downsample dfb
to align it with dfv
. However, I am aware that I need to apply a low-pass filter to avoid aliasing. Can you suggest any improvements to the following function and what is the best way to apply a low-pass filter on a DataFrame before downsampling a time series?
import pandas as pd
from scipy.signal import decimate
# Minimal reproducible example
# Generate example dataframes
lenb =5000
lenv =200
dfb = pd.DataFrame({'a': np.arange(0, lenb,1)}, index=pd.date_range('2022-01-01', periods=lenb, freq='2s'))
dfv = pd.DataFrame({'c': np.arange(0, lenv,1)}, index=pd.date_range('2022-01-01', periods=lenv, freq='10s'))
from scipy.signal import decimate
def newindex(df, ix_new, interp_method='linear'):
"""
Reindex a DataFrame according to the new index *ix_new* supplied.
Args:
df: [pandas DataFrame] The dataframe to be reindexed
ix_new: [np.array] The new index
interp_method: [str] Interpolation method to be used; forwarded to `pandas.DataFrame.reindex.interpolate`
Returns:
df3: [pandas DataFrame] DataFrame interpolated and reindexed to *ixnew*
"""
# create combined index from old and new index arrays
ix_com = np.unique(np.append(df.index, ix_new))
# sort the combined index (ascending order)
ix_com.sort()
# re-index and interpolate over the non-matching points
df2 = df.reindex(ix_com).interpolate(method=interp_method)
# drop all the old index points by re-indexing to new index
df3 = df2.reindex(ix_new)
#print(len(df3)), print(len(ix_new))
return df3
def downsample_dataframe(dfb, dfv, filter_order=3):
freq_dfb = pd.infer_freq(dfb.index)
freq_dfv = pd.infer_freq(dfv.index)
q = int(pd.to_timedelta(freq_dfv).total_seconds()/pd.to_timedelta(freq_dfb).total_seconds())
dfb_downsampled = pd.DataFrame()
for column_name in dfb.columns:
signal = dfb[column_name]
signal = decimate(signal, q, zero_phase=True, axis=0, n=filter_order)
dfb_downsampled[column_name] = signal
# Create new index starting from dfb.index[0] with a cadence of freq_dfv
new_index = pd.date_range(start=dfb.index[0], freq=freq_dfv, periods=len(signal))
dfb_downsampled.index = new_index
# Now reindex dfb to index of dfv
dfb_downsampled = func.newindex(dfb_downsampled, dfv.index)
return dfb_downsampled
dfb_downsampled = downsample_dataframe(df_B, df_V, filter_order=3)
Are there any suggestions on how to improve this function? Is there a suggested method for aligning two timeseries?
scipy.signal.decimate
? $\endgroup$