可以将2D列表用作边界索引吗?

时间:2019-06-24 07:50:35

标签: python pandas numpy indexing

我之前的代码为我提供了一个有趣区域的参考列表边界的每个条目,以及另一个列表的索引。 例如,我有一个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)]

因此,对于我来说,这部分速度已经足够快了。有了Drecker和nakor的提示,它的速度仍然略快。现在的问题是我有样本的候选人,但我仍然必须执行以下任务:

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

2 个答案:

答案 0 :(得分:1)

使用直接切片:

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

如果values是numpy数组,则速度至少会更快。

但是,这只是数据的简单副本,如果花费的时间太长(我认为),那么您就无法做很多事情。但是,如果这确实是瓶颈,也许您不需要复制所有这些数据,而是可以在values数组中使用只读的格式?很难说,因为您在问题中没有提及您对他们的处理方式。

答案 1 :(得分:0)

为了补充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