问题描述
如果标题看起来含糊不清,我很抱歉,但我已经尽力了。无论如何,我有一个包含三列的数据框,一列包含日期时间值(用于观察时间),另一列包含范围(与进行观察的仪器的距离),最后一列包含观察强度。此数据的散点图如下所示:
我需要过滤掉随机孤立的“盐和胡椒”观察,并计划使用中值滤波器来做到这一点。但是,我不确定如何执行此操作。我试图创建一个包含根据时间和范围索引的强度值的二维数组。所以 00:00 UT 对应于第 0 行,0 km 对应于第 0 列等等......空位置包含 NaN。然后我将中值滤波器(scipy 的 medfilt:scipy.ndimage.median_filter)应用到这个二维数组。
我的问题是它似乎效率低下,因为我不得不遍历大量数据来创建数组。而且,当然,将过滤后的二维数组转换为相应的一维序列是很困难的。
def get2DData(df,filt_size):
'''
Implementing this method: We want a 2D array that stores all the LoS
veLocities,so that we can ultimately apply median filtering to it.
To do this,iterate over all unique datetime values and all unique range values,assigning LoS veLocity values to the appropriate positions in a 2D array.
'''
arr = np.empty((len(df['time'].unique()),len(df['slist'].unique()),))
arr[:] = np.nan
times_ = sorted(df['time'].unique())
times_index = np.arange(len(times_))
range_ = sorted(df['slist'].unique())
range_index = np.arange(len(range_))
times_dict = {A: B for A,B in zip(times_,times_index)}
range_dict = {A: B for A,B in zip(range_,range_index)}
times_dict_rev = {A: B for A,B in zip(times_index,times_)}
range_dict_rev = {A: B for A,B in zip(range_index,range_)}
for dt,rng_,v in zip(df['time'].values,df['slist'].values,df['v'].values):
arr[times_dict[dt]][range_dict[rng_]] = v
medfilt_arr = applyFilt(arr,filt_size)
dt_list = []
rng_list = []
v_list = []
for ix,iy in np.ndindex(medfilt_arr.shape):
dt_list.append(times_dict_rev[ix])
rng_list.append(range_dict_rev[iy])
v_list.append(medfilt_arr[ix][iy])
df_filtered = pd.DataFrame({'time': dt_list,'slist': rng_list,'v': v_list})
return arr,df_filtered
解决方法
加速数组创建的一种方法是
def get2DArray(df):
alltime = df['time'].to_numpy()
allrange = df['slist'].to_numpy()
unique_time = np.unique(alltime)
unique_rang = np.unique(allrange)
row = unique_time.searchsorted(alltime)
col = unique_rang.searchsorted(allrange)
arr = np.full((len(unique_time),len(unique_rang)),fill_value=np.NaN)
arr[row,col] = df["v"].to_numpy()
return arr
这个想法是在所有可能的值中使用时间和范围的相对位置来查找关联的行/列,而不是使用字典。在我做的一些测试中,这个版本快了大约 5-7 倍,虽然不是很多,但已经很好了