【问题标题】:Is it possible to use a 2D-list as border index?是否可以使用二维列表作为边界索引?
【发布时间】:2019-11-05 23:50:32
【问题描述】:

我之前的代码为我提供了一个有趣区域的参考列表边界的每个条目以及另一个列表的索引。 例如,我有一个 listA,它应该分配给另一个 listB 中的值。对于每个条目,应该可以获得索引,所以这是有效的:

listA[:]-d/2 <= listB[indices to find] <= listA[:]+d/2

我通过列表理解解决了这个问题,并使用带有边界索引的 python 内置 range() 方法作为参数来获取所有必需的值。所以我遍历我的边界列表并生成一个包含所有索引的列表。所以例如: borders[0,:] = [1,4] 变为 indices[0] = [1,2,3]

arr = [values[range(borders[i,0], borders[i,1])] for i in range(borders.shape[0])]

它可以工作,但对于大型数据集来说太慢了。我发现列表理解是问题所在。有没有一种我可以使用的 numpy/pandas/... 方法,它是一种矩阵运算?

数据集类似如下:

    no_points = 10000
    no_groups = 3
    meas_duration = 60
    df_AT = pd.DataFrame(np.transpose([np.sort(np.random.rand(no_points)*meas_duration) for _ in range(no_groups)]), columns = ['AT {}'.format(i+1) for i in range(no_groups)])
    df_TT = pd.DataFrame(np.transpose([np.random.rand(no_points) for _ in range(no_groups)]), columns = ['TT {}'.format(i+1) for i in range(no_groups)])
    df = pd.concat([df_AT, df_TT], axis=1)
    filterCoincidence(df, window=1e-3)

\\ 编辑 不幸的是,我仍在努力。我将复制一段代码:

        # process coincidence
        borders = [list() for _ in range(len(AT_cols)-1)]
        test = np.empty((AT_df.shape[0],3), dtype=object)
        test[:,0] = np.arange(AT_df.shape[0])
        for i, [AT, TT] in enumerate(zip(AT_cols[np.where(AT_cols != AT_cols[used_ref])], TT_cols[np.where(AT_cols != AT_cols[used_ref])])):
            AT_ix = np.argwhere(AT_cols == AT).flatten()[0]
            neighbors_lower = np.searchsorted(AT_df[AT].values, AT_df[AT_cols[used_ref]]-window, side='left')
            neighbors_upper = np.searchsorted(AT_df[AT].values, AT_df[AT_cols[used_ref]]+window, side='left')

            borders[i] = np.transpose([neighbors_lower, neighbors_upper])
            coinc_ix = np.where(np.diff(borders[i], axis=1).flatten() != 0)[0]

            test[coinc_ix,i+1]=np.asarray([np.arange(borders[i][j][0], borders[i][j][1], dtype=int) for j in coinc_ix])

        test = test[~np.any(pd.isnull(test), axis=1)]

所以现在这部分对于我的目的来说已经足够快了。有了德雷克和纳克的提示,速度还是稍快一些。问题是现在我有候选样本,但我仍然需要执行以下任务:

  • 根据第一个标准对样本进行排序:哪个最相似?所以我必须比较运输时间和到达时间(AT 和 TT 两列)。我可以用sorted(key=my_fun) 来做,但这真的很耗时
  • 检查是否所有样本都在时间窗口内。与参考数据相比,这已实现,但是来自两个非参考组的测量值是否也在时间窗口内?我可以通过在代码中仅使用 +- window/2 来简化问题,但这是一个非常强大的假设,因为参考测量值应始终位于时间窗口的中间。因此我使用了scipy.spatial.distance.cdist() 并检查了距离

【问题讨论】:

    标签: python pandas numpy indexing


    【解决方案1】:

    为了补充 Drecker 的评论,我在我的机器上做了一些测试,如果 values 是一个 numpy 数组,它在 10,000x10,000 矩阵上的速度大约是 10 倍:

    # Generate random data
    import numpy as np
    
    N=10000
    values = np.random.randint(0,100,[N,N]).astype(int)
    borders = []
    for _ in range(N):
        inf = np.random.randint(0,99)
        sup = np.random.randint(inf,100)
        borders.append([inf,sup])
    borders = np.array(borders)
    
    In [1]: %time arr = [values[range(borders[i,0], borders[i,1])] for i in range(borders.shape[0])]
    CPU times: user 7.97 s, sys: 7.27 s, total: 15.2 s
    Wall time: 17.5 s
    
    In [2]: %time arr=[values[borders[i,0]: borders[i,1]] for i in range(borders.shape[0])]
    CPU times: user 30.7 ms, sys: 1.4 s, total: 1.43 s
    Wall time: 1.43 s
    
    
    

    【讨论】:

      【解决方案2】:

      使用直接切片:

      arr = [values[border_pair[0]:border_pair[1]] for border_pair in borders]
      

      如果 values 是 numpy 数组,这至少会快一些。

      但是,这只是您的数据的简单副本,如果花费的时间太长(我认为),您就无能为力了。但是,如果这真的是瓶颈,也许您不需要复制所有这些数据,但您可以在 values 数组中以只读方式使用?很难说,因为你没有在问题中提到你对他们做了什么。

      【讨论】:

      • 谢谢您,我已经可以根据您的提示将速度提高大约 5 秒(从 7 秒)!回答另一个问题:我有三个独立的组,我想将一个样本分配给另一个。组的第一列(到达时间 AT)是一个时间序列,因此已排序。分配的第一个条件是样本在指定距离内,例如0.001 秒。第二个条件是,如果多个样本满足第一个条件,则考虑样本的属性,即传输时间 TT。从而选择最相似的候选人。
      • 我刚刚用数据集的示例编辑了主帖。这些值的数量级不同,但我希望它有助于理解数据结构。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      相关资源
      最近更新 更多