2017-08-11 203 views
3

我想用我的陣列a中的每一行替換第一個x值並保留所有其他值NaN 。然而,第一個x值在每一行都有變化,並由列表b確定。python如何取代陣列(x,n)中每個x的第一個f(x)值

因爲我對陣列不是很熟悉,所以我想我可以用for循環來做到這一點,如下所示,但這不起作用 (我從How to set first N elements of array to zero?獲得了有關數組替換基礎的靈感) 。

In: 
a = np.empty((3,4)) 
a.fill(np.nan) 
b = [2,3,1] 

for i in range(b): 
    a[0:b[i]] = [1] * b[i] 
    a[i:] = np.ones((b[i])) 
pass 

Out: 
line 7: 
ValueError: could not broadcast input array from shape (2) into shape (2,4) 

結果應該是這樣的:

Out: 
[[1, 1, nan, nan], 
[1, 1, 1, nan], 
[1, nan, nan, nan]] 
+1

當你發佈這樣的代碼時,你應該說比'它不工作'。什麼問題?什麼樣的錯誤?一個小調整得到它的工作:'對於我在範圍(3):a [i,0:b [i]] = 1'您沒有完全應用鏈接的答案。 – hpaulj

+0

@hpaulj你說得對,我已經添加了它的完整性。如果我使用你的調整,由最後一行引起的錯誤出現'(ValueError:無法從形狀(2)廣播輸入數組到形狀(3,4))''。如果我刪除這一行,確實很好! –

+0

@hpaulj我的壞,它不起作用。整個陣列比填充一個。然而,你的枚舉解決方案完美工作 –

回答

2

在鏈接的答案,How to set first N elements of array to zero?

數組的解決方案是

y = numpy.array(x) 
y[0:n] = 0 

在其他如果我們用相同的數字填充切片(指數範圍),我們可以指定一個標量。它可以是相同大小的數組,例如np.ones(n)。但它不一定是。

所以我們只需要遍歷的a行(和b元素),並執行該索引分配

In [368]: a = np.ones((3,4))*np.nan 
In [369]: for i in range(3): 
    ...:  a[i,:b[i]] = 1 
    ...:  
In [370]: a 
Out[370]: 
array([[ 1., 1., nan, nan], 
     [ 1., 1., 1., nan], 
     [ 1., nan, nan, nan]]) 

有「填充」原陣列nan的各種方式。np.full做了np.empty後跟copyto

行迭代的變體是for i,n in enumerate(a):

在協調意義上迭代的另一個好方法是使用zip

In [371]: for i,x in zip(b,a): 
    ...:  x[:i] = 1 

這利用了以下事實的優點,關於它的行的二維數組迭代迭代。所以xa的1d視圖,可以在原地更改。

但有一點索引欺騙,我們甚至不必循環。

In [373]: a = np.full((3,4),np.nan) 

In [375]: mask = np.array(b)[:,None]>np.arange(4) 
In [376]: mask 
Out[376]: 
array([[ True, True, False, False], 
     [ True, True, True, False], 
     [ True, False, False, False]], dtype=bool) 
In [377]: a[mask] = 1 
In [378]: a 
Out[378]: 
array([[ 1., 1., nan, nan], 
     [ 1., 1., 1., nan], 
     [ 1., nan, nan, nan]]) 

這是頂級numpy海報之一,@Divakar的最愛。

Numpy: Fix array with rows of different lengths by filling the empty elements with zeros

它可以用來pad列表的列表。說到填充,itertools有一個方便的工具,zip_longest(PY 3名)

In [380]: np.array(list(itertools.zip_longest(*[np.ones(x).tolist() for x in b],fillvalue=np.nan))).T 
Out[380]: 
array([[ 1., 1., nan], 
     [ 1., 1., 1.], 
     [ 1., nan, nan]]) 

你的問題應該已經指定了什麼是錯的;你有什麼樣的錯誤:

for i in w2: 
    a[0:b[i]] = [1] * b[i] 
    a[i:] = np.ones((b[i])) 

w2是不確定的,但可能是range(3)

a[0:b[i]]是錯誤的,因爲它指定所有行,因爲您一次只處理一個行。 a[i:]也指定了一系列的行。

+0

很好的答案!我猜想涉及面具的解決方案是最快的。 'mask = np.array(b)[:, None]> np.arange(4)''是純粹的天才:) –

+0

非常感謝,很好的解釋:)爲了完整性,我將取代w2並寫下我得到的錯誤。 –

2

您可以通過一個循環做到這一點。初始化一個nan值的數組,然後循環遍歷前n個列表,並根據每行的n將值設置爲1。

a = np.full((3, 4), np.nan) 
b = [2, 3, 1] 
for i, x in enumerate(b): 
    a[i, :x] = 1 
+3

你可以使用['numpy.full'](https://docs.scipy.org/doc/numpy/reference/generated/numpy.full.html#numpy-full)來初始化你的矩陣與'np.NAN'值而不是零。 'a = np.full((3,4),np.NAN)'否則很好的解決方案! –

+0

如果我把我的數組全部納入開始,那麼是否將其排列在最前面,而不是將它們設置爲零,而不是使用最後一行使所有剩餘零爲零?也許速度? –

+1

@SVerhoef,主要**可讀性**,imo有時比速度最重要。 –

0
import numpy as np 
a = np.random.rand(3,4) #Create matrix with random numbers (you can change this to np.empty or whatever you want. 
b = [1, 2, 3] # Your 'b' list 
for idr, row in enumerate(a): # Loop through the matrix by row 
    a[idr,:b[idr]] = 1 # idr is the row index, here you change the row 'idr' from the column 0 to the column b[idr] that will be 0, 1 and 3 
    a[idr,b[idr]:] = 'NaN' # the values after that receive NaN 
print(a) # Outputs matrix 
#[[ 1. nan nan nan] 
[ 1. 1. nan nan] 
[ 1. 1. 1. nan]] 
+0

這是一個已經發布的答案的過於複雜的副本 –

+0

答案在13分鐘前發佈,imo可以downvote已經解決的事情的重複答案,但是當我開始做這個時,其他答案甚至沒有發佈,我現在纔看到它。 –

1

可以初始化你爲基質使用列表理解:

>>> import numpy as np 
>>> b = [2, 3, 1] 
>>> max_len = 4 
>>> gen_array = lambda i: [1] * i + [np.NAN] * (max_len - i) 
>>> np.matrix([gen_array(i) for i in b]) 

隨着詳細步驟:

[1] * N將創建長度Ñ填充有1的數組:

>>> [1] * 3 
[1, 1, 1] 

可以使用+ Concat的數組:

>>> [1, 2] + [3, 4] 
[1, 2, 3, 4] 

你只需要兩個[1] * X + [np.NAN] * (N - X)合併將創建充滿X1

最後一個列表理解ň維數組:

[i for i in b]

是一條 「捷徑」(不是真的,但它更容易理解)爲:

a = [] 
for i in b: 
    a.append(i) 
相關問題