2013-11-27 52 views
1

我有一個很大的4D數據集,需要從它創建一個更小的4D數組。我對python相當陌生,用於IDL或matlab。我讀了我的值,然後使用where函數,找到我需要的更小的一維數組的每個維度的索引號。我想創建這些索引號的新數組,但我不斷收到形狀不匹配錯誤(不能broacast到一個單一的形狀。如何從一個較大的數組創建一個較小的數組python

import numpy as n 
import matplotlib.pyplot as plt 
import Scientific.IO.NetCDF as S 

file=S.NetCDFFile('wspd.mon.mean.nc',mode='r') #Opening File 
Lat=file.variables['lat'].getValue()  # Reading in the latitude variables, 73 
Lon=file.variables['lon'].getValue()  # Reading in the longitude variables, 144 
Level=file.variables['level'].getValue() # Reading in the levels, 17 of them 
Defaulttime=file.variables['time'].getValue() # Reading in the time, hrs since 1-1-1 
Defaultwindspeed=file.variables['wspd'].getValue()  # Reading in the windspeed(time, level, lat, lon) 

Time=n.arange(len(Defaulttime))/12.+1948 #Creates time array into readable years with 12 months 
goodtime=n.where((Time>=1948)&(Time<2013)) #Creates a time array for the years that I want, 1948-2012, since 2013 only has until October, I will not be using that data. 
goodlat=n.where((Lat>=35)&(Lat<=50)) #Latitudes where the rockies and plains are in the US 
plainslon=n.where((Lon>=275)&(Lon<=285)) 

Windspeedsplains=Defaultwindspeed[goodtime,:,goodlat,plainslon] 

以下信息由上述的(最後一行行所產生的錯誤碼)。

>>>ValueError: shape mismatch: objects cannot be broadcast to a single shape 
+1

我懷疑任何人都可以幫你解決這個問題。你至少可以做的是找出哪條線實際上是失敗的 – Hammer

+0

'Defaultwindspeed'實際上是4D嗎?使用'Defaultwindspeed.shape'或'Defaultwindspeed.ndim'來檢查... – atomh33ls

+0

@ atomh33ls它必須是,否則錯誤會是'索引太多'。我認爲問題的形式是「goodtime」,「goodlat」和「plainslon」。 @Cwilliams,如果你印刷'goodtime.shape,goodlat.shape,plainslon.shape',你會得到什麼? – askewchan

回答

0

正在發生的事情是,每個索引的的長度(where)陣列將是不同的,因此貴輸出陣列的形狀是不明確的,因此錯誤。要強制廣播到適當的形狀,你必須重塑你的陣列播出一個適當的形狀,如下所示:

Windspeedsplains = Defaultwindspeed[goodtime[0][:, None, None, None],:,goodlat[0][:,None],plainslon[0]] 

[0]的是有監守np.where(a)返回長度a.ndim的元組與該元組是最適合自己的條件的索引的陣列中的每個元素。我假設你所有的布爾數組都是1d,所以所有的where輸出都將是長度爲1的元組,所以我們只需要它的一個數組,因此[0]

當我們得到數組後,我們想要重塑它以匹配你想要的輸出數組所具有的形狀。可推測,你的輸出應該有的形狀是(goodtime.size, Defaultwindspeed.shape[1], goodlat.size, plainslon.size),所以你必須讓每個索引數組的形狀與輸出數組應該隨該變量而變化的軸相匹配。例如,對於goodtime,您希望Windspeedplains根據軸的0軸的時間變化。因此,goodtime本身也必須沿着四軸的軸0變化,因此您強制索引數組的形狀爲(N, 1, 1, 1),這就是[:, None, None, None]所做的。

所以,你可以把上面的行更具可讀性有:

goodtime = n.where((Time>=1948)&(Time<2013))[0][:, None, None, None] 
goodlat = n.where((Lat>=35)&(Lat<=50))[0][:, None] 
plainslon = n.where((Lon>=275)&(Lon<=285))[0] 

Windspeedsplains=Defaultwindspeed[goodtime, :, goodlat, plainslon] 

或實際,因爲你可以直接與布爾數組索引:

goodtime = ((Time>=1948)&(Time<2013))[:, None, None, None] 
goodlat = ((Lat>=35)&(Lat<=50))[:, None] 
plainslon = ((Lon>=275)&(Lon<=285)) 

Windspeedsplains=Defaultwindspeed[goodtime, :, goodlat, plainslon] 

這裏是一個略微簡單的例子:

In [52]: a = np.arange(3*3*3).reshape(3,3,3) 

In [53]: a 
Out[53]: 
array([[[ 0, 1, 2], 
     [ 3, 4, 5], 
     [ 6, 7, 8]], 

     [[ 9, 10, 11], 
     [12, 13, 14], 
     [15, 16, 17]], 

     [[18, 19, 20], 
     [21, 22, 23], 
     [24, 25, 26]]]) 

In [54]: mask0 = np.where(a[:,0,0] >= 9) 

In [55]: mask0 
Out[55]: (array([1, 2]),) # <-- this is the length 1 tuple I was talking about. we want the array inside. 

In [56]: mask1 = np.where(a[0,:,0]%2 == 0) 

In [57]: mask1 
Out[57]: (array([0, 2]),) 

In [62]: mask2 = np.where(a[0,0,:] < 1) 

In [63]: mask2 
Out[63]: (array([0]),) 

In [67]: b = a[mask0[0][:, None, None], mask1[0][:, None], mask2[0]] 

In [68]: b 
Out[68]: 
array([[[ 9], 
     [15]], 

     [[18], 
     [24]]]) 

In [69]: b.shape 
Out[69]: (2, 2, 1) 
相關問題