我有一个尺寸为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。
任何人都可以帮助我吗?感谢。
答案 0 :(得分:3)
假设vec
是numpy.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 Weckesser在a 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
进行1
和vec
映射。对于索引部分,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