[英]Numpy list comprehension iterating over 2D array
我有一些代碼可以加載一組長(100k-1mil)行,它在第一列中有一個索引,后跟18個值,每行總共19個浮點數。 所有這些都放入一個numpy數組中。
我需要對矩陣進行一些簡單的處理,以保留索引列並根據值是正數還是負數的條件得出1和0,但是准則會有所不同,因為列是具有不同參考值的連續值對。
下面的代碼首先通過2-19列進行偶數運算,然后通過奇數運算檢查值,然后創建一個臨時列表以放入我想要的數組末尾。
我知道有一種更簡單的方法可以做到這一點,即列表理解和lambda,但我對此並不熟練。 因此,我希望有人可以幫助我將這段代碼的長度縮短為更緊湊的形式。 效率也更高,但是我知道緊湊的方法並不總是能提高效率。 但是,無論有沒有numpy,它都將幫助我更好地理解列表理解。
供參考的樣本值:
0.000 72.250 -158.622 86.575 -151.153 85.807 -149.803 84.285 -143.701 77.723 -160.471 96.587 -144.020 75.827 -157.071 87.629 -148.856 100.814 -140.488
10.000 56.224 -174.351 108.309 -154.148 68.564 -155.721 83.634 -132.836 75.030 -177.971 100.623 -146.616 61.856 -150.885 92.147 -150.124 91.841 -153.112
20.000 53.357 -153.537 58.190 -160.235 77.575 176.257 93.771 -150.549 77.789 -161.534 103.589 -146.363 73.623 -159.441 99.315 -129.663 92.842 -138.736
這是代碼片段:
datain = numpy.loadtxt(testfile.txt) #load data
dataout = numpy.zeros(datain.shape) # initialize empty processing array
dataout[:, 0] = datain[:, 0] # assign time values from input data to processing array
dataarray = numpy.zeros(len(datain[0]))
phit = numpy.zeros((len(dataarray)-1)/2)
psit = numpy.zeros((len(dataarray)-1)/2)
for i in range(len(datain)):
dataarray = numpy.copy(datain[i])
phit[:] = dataarray[1::2]
psit[:] = dataarray[2::2]
temp = []
for j in range(len(phit)):
if(phit[j] < 0):
temp.append(1)
else:
temp.append(0)
if(psit[j] > 0):
temp.append(1)
else:
temp.append(0)
dataout[i][1:] = temp
預先感謝,我知道這里有很多關於這些主題的問題; 不幸的是,我找不到能幫助我找到解決方案的解決方案。
正如@abarnert提到的,這里的解決方案不是編寫更好的循環,而是(因為您使用的是Numpy)通過理解如何以更高級的方式使用Numpy來完全不循環Python。
你有一個矩陣像
[ [idx, v0a, v0b, v1a, v1b, ... ], ... ]
你想要一個基本上是
[ [idx, 1 if v0a < 0 else 0, 1 if v0b > 0 else 0, ... ], ... ]
我們將分兩步執行此操作:首先,我們將對矩陣進行略微變換,以使比較都相同; 其次,我們將就地應用比較。
我們如何處理“偶數”和“奇數”列之間的唯一區別是,一個要檢查<0,另一個要檢查> 0。 如果我們通過將它們乘以-1來修改第二組列,則這些比較都將簡單地變為<0:
datain[:, 2::2] *= -1
現在我們只想知道,對於每個值(第一列之后),該值是否都小於0。 這非常簡單:
datain[:, 1:] < 0
這將返回一個布爾值矩陣,其中的每個值表示datain[:, 1:]
的對應單元格是否小於0。您希望將它們作為整數,1表示True,0表示False。 事實證明,當我們將這些布爾值分配回我們的原始數組(包含浮點數)時,numpy會自動將布爾值轉換為浮點數; True將被強制轉換為1.0,而False將被強制轉換為0.0。
如果您不想丟棄原始數據,只需先將其復制掉即可。 這是完整的代碼:
# If you want to preserve your old data, create a copy for us to modify
dataout = np.array(datain)
# Now assign your integer values into your data array
dataout[:, 2::2] *= -1
dataout[:, 1:] = datain[:, 1:] < 0
對於您提供的樣本輸入:
array([[ 0. , 72.25 , 158.622, 86.575, 151.153, 85.807,
149.803, 84.285, 143.701, 77.723, 160.471, 96.587,
144.02 , 75.827, 157.071, 87.629, 148.856, 100.814,
140.488],
[ 10. , 56.224, 174.351, 108.309, 154.148, 68.564,
155.721, 83.634, 132.836, 75.03 , 177.971, 100.623,
146.616, 61.856, 150.885, 92.147, 150.124, 91.841,
153.112],
[ 20. , 53.357, 153.537, 58.19 , 160.235, 77.575,
-176.257, 93.771, 150.549, 77.789, 161.534, 103.589,
146.363, 73.623, 159.441, 99.315, 129.663, 92.842,
138.736]])
該代碼最終具有以下最終結果:
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0.],
[10., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0.],
[20., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0.]])
感謝abarnert以此向我指出正確的方向,解決方案非常簡單。
datain = numpy.loadtxt(testfile.txt) #load data
dataout = numpy.empty(datain.shape, dtype=int) # initialize empty processing array
dataout[:, 0] = datain[:, 0] # assign time values from input data to processing array
dataout[:, 1::2] = datain[:, 1::2] < 0
dataout[:, 2::2] = datain[:, 2::2] > 0
而已! 更短,更易讀,並且為我提供了我想要的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.