矢量化方法将1维布尔数组更改为2维,python 3

时间:2017-08-28 06:41:31

标签: arrays python-3.x numpy boolean vectorization

我有一个尺寸为1 * n的布尔矢量,假设为n = 6

vec = [1, 0, 1, 0, 0, 1]

我想将其更改为n * 2矩阵。对于vec中的每个元素,如果它是1,则在矩阵中相应的行应为[1, 0];如果是0,则相应的行应为[0, 1]。所以得到的矩阵应该是

matr = [[1, 0],
        [0, 1],
        [1, 0],
        [0, 1],
        [0, 1],
        [1, 0]]

要将矢量转换为矩阵,我需要一种优雅的矢量化方法(避免for-loops),因为实际情况n会比6大得多。 这种转换的原因是机器学习分类purppose。 vec引用binary classification,matr将用于categorical classification。也许这些信息可以使我的问题更加具体。

我使用Python 3,numpy / scipy,sklearn。

任何人都可以帮助我吗?感谢。

2 个答案:

答案 0 :(得分:3)

假设vecnumpy.array

vec = np.array([1, 0, 1, 0, 0, 1])

然后,您可以按列方式将其堆叠,按位XOR,以翻转0-> 1和1-> 0的值,例如:

out = np.stack((vec, vec ^ 1), axis=1)

给你:

array([[1, 0],
       [0, 1],
       [1, 0],
       [0, 1],
       [0, 1],
       [1, 0]])

感谢Warren Weckessera comment建议更快的广播方式:

vec[:,None] ^ [0, 1]

基本时间:

In [33]: %timeit np.stack((a, a ^ 1), axis=1)
15.6 µs ± 199 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [34]: %timeit a[:,None] ^ [0, 1]
7.4 µs ± 45.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

答案 1 :(得分:2)

这是一种使用数组索引的方法。基本上,我们会使用2D数组,其中包含两个子数组,用于从0进行1vec映射。对于索引部分,np.take对于这样的重复索引非常有效。实现看起来像这样 -

mapping = np.array([[0,1],[1,0]])
out = np.take(mapping, vec, axis=0)

示例运行 -

In [115]: vec = np.array([1, 0, 1, 0, 0, 1])

In [116]: np.take(np.array([[0,1],[1,0]]), vec, axis=0)
Out[116]: 
array([[1, 0],
       [0, 1],
       [1, 0],
       [0, 1],
       [0, 1],
       [1, 0]])

更大的数据集上的运行时测试 -

In [108]: vec = np.random.randint(0,2,(10000000))

# @Jon Clements's soln
In [109]: %timeit np.stack((vec, vec ^ 1), axis=1)
10 loops, best of 3: 50.2 ms per loop

# @Warren Weckesser's suggestion soln
In [110]: %timeit vec[:,None] ^ [0, 1]
10 loops, best of 3: 90 ms per loop

# Proposed in this post
In [111]: %timeit np.take(np.array([[0,1],[1,0]]), vec, axis=0)
10 loops, best of 3: 31 ms per loop