从一组 3 个一维向量创建一个包含强度值的二维数组

问题描述

如果标题看起来含糊不清,我很抱歉,但我已经尽力了。无论如何,我有一个包含三列的数据框,一列包含日期时间值(用于观察时间),另一列包含范围(与进行观察的仪器的距离),最后一列包含观察强度。此数据的散点图如下所示:

enter image description here

我需要过滤掉随机孤立的“盐和胡椒”观察,并计划使用中值滤波器来做到这一点。但是,我不确定如何执行此操作。我试图创建一个包含根据时间和范围索引的强度值的二维数组。所以 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 倍,虽然不是很多,但已经很好了