4

我需要創建一個2D數組,其中每行可以以不同的數字開始和結束。假設給出每行的第一個和最後一個元素,並根據行的長度對所有其他元素進行插值。在一個簡單的例子中,假設我想創建一個3X3的數組,其起點爲0,但是不同的末端由下面的W給出:向量化的NumPy linspace用於多個啓動和停止值

array([[ 0., 1., 2.], 
     [ 0., 2., 4.], 
     [ 0., 3., 6.]]) 

是否有更好的方法來做到這一點比下面

D=np.ones((3,3))*np.arange(0,3) 
D=D/D[:,-1] 
W=np.array([2,4,6]) # last element of each row assumed given 
Res= (D.T*W).T 
+1

如果你想使用熊貓:'pd.Series(W).apply(lambda:np.linspace(0,e,3))' – Boud

+0

基本上你有兩個向量(矩陣的第一列和最後一列) ,對嗎?然後你會爲每一行插入一些值。 – Kartik

+1

@dayum如果你想改變開始位置,它是一樣的方法,但是你建立一個帶有兩個向量的df,並且你可以再次調用lambda參數df.start,df.end,3 – Boud

回答

4

下面是一個使用broadcasting的方法 -

def create_ranges(start, stop, N, endpoint=True): 
    if endpoint==1: 
     divisor = N-1 
    else: 
     divisor = N 
    steps = (1.0/divisor) * (stop - start) 
    return steps[:,None]*np.arange(N) + start[:,None] 

SAMPL e run -

In [22]: # Setup start, stop for each row and no. of elems in each row 
    ...: start = np.array([1,4,2]) 
    ...: stop = np.array([6,7,6]) 
    ...: N = 5 
    ...: 

In [23]: create_ranges(start, stop, 5) 
Out[23]: 
array([[ 1. , 2.25, 3.5 , 4.75, 6. ], 
     [ 4. , 4.75, 5.5 , 6.25, 7. ], 
     [ 2. , 3. , 4. , 5. , 6. ]]) 

In [24]: create_ranges(start, stop, 5, endpoint=False) 
Out[24]: 
array([[ 1. , 2. , 3. , 4. , 5. ], 
     [ 4. , 4.6, 5.2, 5.8, 6.4], 
     [ 2. , 2.8, 3.6, 4.4, 5.2]]) 
+0

爲什麼不利用'linspace'? – Boud

+0

@Boud我不確定,它是否適用於'2D'? – Divakar

+0

@Divakar我的意思是這樣的[this](http://stackoverflow.com/a/16887295/624829) – Boud

1

與OP的這種使用linspace一樣,假定所有行的開始都是0。

x=np.linspace(0,1,N)[:,None]*np.arange(0,2*N,2) 

(編輯 - 這是我應該得到什麼轉置;要麼調換,或切換使用[:,None]

對於N = 3000,這是明顯快@Divaker's解決方案。我不完全確定爲什麼。

In [132]: timeit N=3000;x=np.linspace(0,1,N)[:,None]*np.arange(0,2*N,2) 
10 loops, best of 3: 91.7 ms per loop 
In [133]: timeit create_ranges(np.zeros(N),np.arange(0,2*N,2),N) 
1 loop, best of 3: 197 ms per loop 
In [134]: def foo(N): 
    ...:  D=np.ones((N,N))*np.arange(N) 
    ...:  D=D/D[:,-1] 
    ...:  W=np.arange(0,2*N,2) 
    ...:  return (D.T*W).T 
    ...: 
In [135]: timeit foo(3000) 
1 loop, best of 3: 454 ms per loop 

============

隨着啓動和停止,我可以使用:

In [201]: starts=np.array([1,4,2]); stops=np.array([6,7,8]) 
In [202]: x=(np.linspace(0,1,5)[:,None]*(stops-starts)+starts).T 
In [203]: x 
Out[203]: 
array([[ 1. , 2.25, 3.5 , 4.75, 6. ], 
     [ 4. , 4.75, 5.5 , 6.25, 7. ], 
     [ 2. , 3.5 , 5. , 6.5 , 8. ]]) 

隨着額外的計算,使得比create_ranges有點慢。

In [208]: timeit N=3000;starts=np.zeros(N);stops=np.arange(0,2*N,2);x=(np.linspace(0,1,N)[:,None]*(stops-starts)+starts).T 
1 loop, best of 3: 227 ms per loop 

所有這些解決方案都只是變化做startsstops之間的線性插值的想法。

+0

由於問題陳述了每一行的第一個和最後一個元素,因此如何將每行的開始和結束值合併到基於linspace的解決方案中? – Divakar