查找每个阵列由一行组成的所有组合

时间:2019-03-29 14:56:48

标签: python numpy combinations

  • 我有多个二维数组。
  • 我想找到每个数组中包含一行的所有组合。

示例:

比方说,数组A具有行a0,a1,a2。 假设数组B的行为b0,b1

六个组合是:

a0-b0,a0-b1,a1-b0, a1-b1,a2-b0,a2-b1

破折号代表串联(np.hstack

如何快速处理任意数量的数组(例如,A,B,C,...)?

2个数组的快速方法:Combination of all rows in two numpy arrays

合并3个数组的代码结果:

# input arrays:
[[0 1 2]]
[[ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
[[17 18 19 20 21 22 23]
 [24 25 26 27 28 29 30]
 [31 32 33 34 35 36 37]]
# output:
[[ 0  1  2  5  6  7  8  9 17 18 19 20 21 22 23]
 [ 0  1  2  5  6  7  8  9 24 25 26 27 28 29 30]
 [ 0  1  2  5  6  7  8  9 31 32 33 34 35 36 37]
 [ 0  1  2 10 11 12 13 14 17 18 19 20 21 22 23]
 [ 0  1  2 10 11 12 13 14 24 25 26 27 28 29 30]
 [ 0  1  2 10 11 12 13 14 31 32 33 34 35 36 37]
 [ 0  1  2 15 16 17 18 19 17 18 19 20 21 22 23]
 [ 0  1  2 15 16 17 18 19 24 25 26 27 28 29 30]
 [ 0  1  2 15 16 17 18 19 31 32 33 34 35 36 37]]

代码:

import numpy as np

def form_combinations(xs):
    tot_size = np.sum([x.shape[1] for x in xs])
    n_rows = [x.shape[0] for x in xs]
    out = np.empty(n_rows + [tot_size])
    n_cols = [x.shape[1] for x in xs]
    cs = np.cumsum([0] + n_cols)
    n = np.newaxis
    out[:, :, :, cs[0]:cs[1]] = xs[0][:, n, n, :]
    out[:, :, :, cs[1]:cs[2]] = xs[1][n, :, n, :]
    out[:, :, :, cs[2]:cs[3]] = xs[2][n, n, :, :]
    out = out.reshape(-1, tot_size)
    return out


def main():
    xs = [
        np.arange(3)[np.newaxis, :],
        np.arange(5, 20).reshape(3, 5),
        np.arange(17, 38).reshape(3, 7)
    ]
    print(xs)

    out = form_combinations(xs)
    print(out)

main()

3 个答案:

答案 0 :(得分:1)

一种方法是使用列表推导,只需在所有三个数组上循环,然后使用df2['Hostname'] = df2['Hostname'].str.replace("*", "") 将它们水平堆叠即可。

hstack

时间

np.array([np.hstack((i, j, k)) for i in a for j in b for k in c])

# array([[ 0,  1,  2,  5,  6,  7,  8,  9, 17, 18, 19, 20, 21, 22, 23],
#        [ 0,  1,  2,  5,  6,  7,  8,  9, 24, 25, 26, 27, 28, 29, 30],
#        [ 0,  1,  2,  5,  6,  7,  8,  9, 31, 32, 33, 34, 35, 36, 37],
#        [ 0,  1,  2, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23],
#        [ 0,  1,  2, 10, 11, 12, 13, 14, 24, 25, 26, 27, 28, 29, 30],
#        [ 0,  1,  2, 10, 11, 12, 13, 14, 31, 32, 33, 34, 35, 36, 37],
#        [ 0,  1,  2, 15, 16, 17, 18, 19, 17, 18, 19, 20, 21, 22, 23],
#        [ 0,  1,  2, 15, 16, 17, 18, 19, 24, 25, 26, 27, 28, 29, 30],
#        [ 0,  1,  2, 15, 16, 17, 18, 19, 31, 32, 33, 34, 35, 36, 37]])

答案 1 :(得分:1)

对于任意数量的数组,采用增量方法:

def combine(xs):
    comb=np.array([[]],int)
    for array in xs:
        left  = repeat(comb,len(array),axis=0)
        right = vstack([array]*len(comb))
        comb  = hstack((left,right))
    return comb

答案 2 :(得分:1)

改编自https://stackoverflow.com/a/49445693/7207392

import numpy as np
import operator as op
import itertools as it

def cartesian_product_pp(arrays, out=None):
    la = len(arrays)
    h, w = zip(*map(op.attrgetter('shape'), arrays))
    w = np.fromiter(it.chain([0], w), int, la+ 1)
    W = w.cumsum()
    h = *h, W[la]
    dtype = np.result_type(*arrays)
    arr = np.empty(h, dtype=dtype)
    arrs = *it.accumulate(it.chain((arr,), it.repeat(0, la-1)), np.ndarray.__getitem__),
    idx = slice(None), *it.repeat(None, la-1)
    for i in range(la-1, 0, -1):
        arrs[i][..., W[i]:W[i+1]] = arrays[i][idx[:la-i]]
        arrs[i-1][1:] = arrs[i]
    arr[..., W[0]:W[1]] = arrays[0][idx]
    return arr.reshape(-1, W[la])

# example
a = np.r_[:3].reshape(1, 3)
b = np.r_[5:20].reshape(3, 5)
c = np.r_[17:38].reshape(3, 7)
p = cartesian_product_pp([a, b, c])

输出:

>>> p
array([[ 0,  1,  2,  5,  6,  7,  8,  9, 17, 18, 19, 20, 21, 22, 23],
       [ 0,  1,  2,  5,  6,  7,  8,  9, 24, 25, 26, 27, 28, 29, 30],
       [ 0,  1,  2,  5,  6,  7,  8,  9, 31, 32, 33, 34, 35, 36, 37],
       [ 0,  1,  2, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23],
       [ 0,  1,  2, 10, 11, 12, 13, 14, 24, 25, 26, 27, 28, 29, 30],
       [ 0,  1,  2, 10, 11, 12, 13, 14, 31, 32, 33, 34, 35, 36, 37],
       [ 0,  1,  2, 15, 16, 17, 18, 19, 17, 18, 19, 20, 21, 22, 23],
       [ 0,  1,  2, 15, 16, 17, 18, 19, 24, 25, 26, 27, 28, 29, 30],
       [ 0,  1,  2, 15, 16, 17, 18, 19, 31, 32, 33, 34, 35, 36, 37]])

@ B.M。和@Bazingaa的方法的时间:

>>> timeit(lambda: cartesian_product_pp([a,b,c]), number=1000)*1000
15.173833002336323
>>> timeit(lambda: combine([a,b,c]), number=1000)*1000
31.1394709860906
>>> timeit(lambda: np.array([np.hstack((i, j, k)) for i in a for j in b for k in c]), number=1000)*1000
51.15771805867553