检测元素是否在区间限制对中

时间:2017-04-13 01:20:54

标签: python performance pandas numpy

我有数组:

A = np.array([1, 6,  4, 4, 5, 6])
B = np.array([5, 40, 4, 6, 54,7]) #same size as A but every element of B is greater than corresponding element of A
C = np.array([6, 3])

我想查找AB的所有行,以便C>=AC<=B。相同行的A and B表单对必须一起选择。

因此,输出数组将是:

For C[0] = 6
Aout = [6, 4, 5, 6]
Bout = [40, 6, 54, 7]

ForC[1] = 3
Aout = [1]
Bout = [5]

因此,最终输出看起来像:

Aout = [1, 6, 4, 5, 6]
Bout = [5, 40, 6, 54, 7]

目前我正在考虑使用numpy.where并循环浏览C的每个元素,但考虑到我的文件非常大A, B and C,这似乎是一个非常低效的过程。

如果使用熊猫有更简单的方法,我会更喜欢。

2 个答案:

答案 0 :(得分:4)

特别是如果您有非常大的AB,那么循环C的开销几乎可以忽略不计。但是,如果C很长但AB很短,那么您需要考虑一种广播方法,因为这样会导致一个巨大的开销。

显式循环的简单方法

mask = np.zeros(A.shape, dtype=bool)
for item in C:
    mask |= (A<=item) & (B>=item)

A[mask], B[mask]  # select the valid elements

广播方式

mask= ((A[:, None]<=C) & (B[:, None]>=C)).max(axis=1)

A[mask], B[mask]  # select the valid elements

然而,广播方法会创建大型(size= A.size * C.size)中间数组,因此如果AB C很大,那么需要大量的记忆。

答案 1 :(得分:3)

预期解决方案

似乎df1.drop_duplicates(common_cols).merge(df2.drop_duplicates(common_cols)) A充当下边界和上边界,有点像间隔边界,我们的任务是检测来自B的任何元素是否都在这些间隔。对于此类与边界相关的问题,通常numpy.searchsorted可以与其可选的C参数一起使用,该参数接受sideleft作为输入参数。这个函数让我们得到第一个索引,其中每个要搜索的元素都存在于被赋予right参数的一侧。因此,我们需要查找指数,其中sideleft元素中的每一个的rightA侧面匹配索引分别出现。那些相同的情况将表明该元素位于边界限制的同一侧,即不在该对的边界限制内。因此,我们需要将不平等作为最终衡量标准。

因此,实施将是 -

B

这会给我们一个掩码,比如def ingrps_searchsorted(A, B, C): # searchsorted needs the first input to be sorted S = np.sort(C) # Use searchsorted and look for return np.searchsorted(S, A, 'left') != np.searchsorted(S, B, 'right') ,我们需要屏蔽mA以获得最终输出:BA[m]

运行时测试

其他方法 -

B[m]

制作面具的时间和验证:

# MSeifert's soln1
def ingrps_loop(A, B, C):
    mask = np.zeros(A.shape, dtype=bool)
    for item in C:
        mask |= (A<=item) & (B>=item)
    return mask

# MSeifert's soln2
def ingrps_broadcasting(A, B, C):  
    return ((A[:, None]<=C) & (B[:, None]>=C)).max(axis=1)