创建每行中具有单个交错值的数组?

时间:2017-04-12 10:32:54

标签: python numpy

我需要生成一个nX3的零数组,但其中一列的值在每行中交错(1.0)。

期望的输出:

n = 10
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.]])

我尝试对数组进行切片和重塑,但有些行包含全部零。

我的Attemtp:

n = 10
verts_color = np.zeros(3 * n)
verts_color[::4] = 1
verts_color.reshape((n,3))
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 0.,  0.,  0.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 0.,  0.,  0.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.]])

我找不到一个例子或弄清楚如何自己解决这个问题,并希望有人能够帮我完成这个任务?

3 个答案:

答案 0 :(得分:1)

方法#1

def broadcasting_based(n, m): # n :number of cols, m : number of rows
    return (np.mod(np.arange(m),n)[:,None] == np.arange(n)).astype(float)

方法#2

def tile_based(n, m): # n :number of cols, m : number of rows
    M = 1+((m-1)//n)
    return np.tile(np.eye(n),M).T[:m]

方法#3

def initialization_based(n, m): # n :number of cols, m : number of rows
    M = 1+((m-1)//n)
    r = np.arange(n)
    out = np.zeros((M,n,n))
    out[:,r,r] = 1
    out.shape = (-1,n)
    return out[:m]

还有一个基于初始化,更短的初始化并使用步长切片 -

def initialization_based_v2(n, m): # n :number of cols, m : number of rows
    out = np.zeros((m,n))
    for i in range(n):
        out[i::n,i] = 1
    return out

样品运行 -

In [93]: broadcasting_based(n=3, m = 10)
Out[93]: 
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.]])

In [94]: np.allclose(broadcasting_based(3,10), tile_based(3,10))
Out[94]: True

In [95]: np.allclose(broadcasting_based(3,10), initialization_based(3,10))
Out[95]: True

In [162]: np.allclose(broadcasting_based(3,10), initialization_based_v2(3,10))
Out[162]: True

运行时测试

其他方法 -

# @kmario23's soln
def using_concatenate(m, n):
    return np.concatenate([np.identity(m)]* (n//m + 1), axis=0 )[:n, :]

# @Michael's soln    
def initialization_modassign(m, n):
    x = np.zeros((n,m))
    i = np.arange(n)
    x[i, i%m] = 1
    return x

计时 -

In [188]: %timeit broadcasting_based(3,10000)
     ...: %timeit tile_based(3,10000)
     ...: %timeit initialization_based(3,10000)
     ...: %timeit initialization_based_v2(3,10000)
     ...: %timeit using_concatenate(3,10000)
     ...: %timeit initialization_modassign(3,10000)
     ...: 
1000 loops, best of 3: 225 µs per loop
10000 loops, best of 3: 40.9 µs per loop
10000 loops, best of 3: 23.6 µs per loop
10000 loops, best of 3: 20.7 µs per loop
1000 loops, best of 3: 480 µs per loop
10000 loops, best of 3: 177 µs per loop

In [189]: %timeit broadcasting_based(5,10000)
     ...: %timeit tile_based(5,10000)
     ...: %timeit initialization_based(5,10000)
     ...: %timeit initialization_based_v2(5,10000)
     ...: %timeit using_concatenate(5,10000)
     ...: %timeit initialization_modassign(5,10000)
     ...: 
1000 loops, best of 3: 238 µs per loop
10000 loops, best of 3: 63.6 µs per loop
10000 loops, best of 3: 33.3 µs per loop
10000 loops, best of 3: 33.3 µs per loop
1000 loops, best of 3: 275 µs per loop
10000 loops, best of 3: 176 µs per loop

因此,性能initialization_based_v2似乎运作良好。

答案 1 :(得分:1)

它有点古怪,但它的工作原理是你已经(垂直)堆叠的身份数组,但你需要根据n调整行

n = 10
np.vstack([np.identity(3)]* (n//3 + 1))[:n, :]

或者,如果您希望提高效果,可以使用np.concatenate

np.concatenate([np.identity(3)]* (n//3 + 1), axis=0 )[:n, :]

对于 一般用例&提高性能 使用以下(n, m)分别为行和列的内容。

np.concatenate([np.identity(m)]* (n//m + 1), axis=0 )[:n, :]

示例:

In [151]: n = 10

In [152]: np.vstack([np.identity(3)]* (n//3 + 1))[:n, :]
Out[152]: 
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.]])


# number of columns
In [170]: m = 3

# number of rows
In [171]: n = 10

In [172]: np.concatenate([np.identity(m)]* (n//m + 1), axis=0 )[:n, :]
Out[172]: 
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 1.,  0.,  0.]])

性能:

In [176]: def using_concatenate(n, m):
     ...:     return np.concatenate([np.identity(m)]* (n//m + 1), axis=0 )[:n, :]
     ...: 

In [177]: %timeit using_concatenate(n, m)
10000 loops, best of 3: 22.8 µs per loop

答案 2 :(得分:1)

import numpy as np
n = 10
x = np.zeros((n,3))
i = np.arange(n)
x[i, i%3] = 1