本文**:
numpy的ndarray陣列物件不能像list一樣動態地改變其大小,在做資料採集時很不方便。本文介紹如何通過np.frombuffer()實現動態陣列。
python的列表物件實際上是乙個動態指標陣列。當列表中沒有空間儲存新的元素時,列表會動態地改變其大小,以容納新的元素。每次改變大小時,它都會預留一部分空間,以降低改變大小的頻率。下面的程式可以觀察列表的這一行為。
import程式的輸出如下圖所示,圖中每個階梯跳變的位置都表示一次記憶體分配,而每個階梯的高度表示額外分配的記憶體的大小。sysimport
pylab
aspl
size=
fori
inxrange
(10000
):size.(
sys.
getsizeof
(size
))pl
.plot
(size,lw
="2")pl
.show
()
importpython標準庫中的array陣列也提供了動態分配記憶體的功能,而且它和numpy陣列一樣直接將數值的二進位制資料儲存在一塊記憶體中,因此我們可以先用array陣列收集陣列,然後通過np.frombuffer()將array陣列的資料記憶體直接轉換為乙個numpy陣列。下面是乙個例子:numpy
asnp
class
dynamicarray
(object
):def
__init__
(self
,item_type
):self
._data=np
.zeros(10
,dtype
=item_type
)self
._size=0
defget_data
(self
):return
self
._data
[:self
._size
]def
(self
,value
):if
len(
self
._data)==
self
._size
:self
._data=np
.resize
(self
._data
,int
(len
(self
._data)*
1.25
))self
._data
[self
._size]=
value
self
._size+=1
item_type=np
.dtype
()da
=dynamicarray
(item_type
)foriin
xrange
(100
):da.((
i,i*
0.1,i*
0.2,i*
0.3))
data=da
.get_data
()
>>>array陣列只支援一維,如果我們需要採集多個頻道的資料,可以將這些資料依次新增進array陣列,然後通過reshape()方法將np.frombuffer()所建立的numpy陣列改為二維陣列。下面是乙個例子:import
numpy
asnp
>>>
from
array
import
array
>>> a=
array
("d",[
1,2,
3,4])
# 建立乙個array陣列
>>>
aarray('d', [1.0, 2.0, 3.0, 4.0])
>>> na=
np.frombuffer(a
,dtype=np
.float
)# 通過np.frombuffer()建立乙個和a共享記憶體的numpy陣列
>>>
naarray([ 1., 2., 3., 4.])
>>> na[
1]=20
# 修改numpy陣列中的第乙個元素
>>>
aarray('d', [1.0, 20.0, 3.0, 4.0]) # array陣列中的第乙個元素也同時改變
buf在這個例子中,❶我們通過array陣列buf採集兩個頻道的資料,資料採集完畢之後,我們通過np.frombuffer()將其轉換為numpy陣列,並通過reshape()將其形狀改為(100,2)。=array
("d"
)foriin
range
(100
):buf.(
math
.sin(i
*0.1))❶
buf.(
math
.cos(i
*0.1
))data=np
.frombuffer
(buf
,dtype=np
.float).
reshape(-
1,2)
❷print
data
當每個頻道的資料型別不同時,就不能採用上節所介紹的方法了。這時我們可以使用bytearray收集資料。bytearray是位元組陣列,因此我們首先需要通過struct模組將python的數值轉換成其位元組表示形式。如果資料來自二進位制檔案或者硬體,那麼我們得到得已經是位元組資料,這個步驟可以省略。下面是使用bytearray進行資料採集的例子:
buf❶採集三個頻道的資料,其中頻道1是短整型整數,其型別符號為」h」,頻道2和3為雙精度浮點數,其型別符號為」d」。型別格式字串中的」=」表示輸出得位元組資料不進行記憶體對齊。即一條資料的位元組數為2+8+8=16,如果沒有」=」,那麼一條資料的位元組數則為8+8+8=24。=bytearray
()foriin
range
(100
):buf
.extend
(struct
.pack
("=hdd",i
,math
.sin(i
*0.1
),math
.cos(i
*0.1
)))❶
dtype=np
.dtype()❷
data=np
.frombuffer
(buf
,dtype
=dtype)❸
data
❷定義乙個dtype物件表示一條資料的結構,dtype物件預設不進行記憶體對齊,如果採集資料用的bytearray中的資料是記憶體對齊的話,只需要設定dtype()的align引數為true即可。
❸最後通過np.frombuffer()將bytearray轉換為numpy的結構陣列。然後我們就可以通過data[「id」]、data[「sin」]和data[「cos」]訪問三個頻道的資料了。
np.frombuffer()還可以從字串建立陣列,陣列也和字串共享資料記憶體,但由於字串是不可變物件,因此所建立的陣列是唯讀的。如果不需要修改資料,這種方法比np.fromstring()更快、更節省記憶體。
numpy中使用陣列進行面向陣列程式設計
一 將條件邏輯作為陣列操作 一 numpy.where函式 1 定義 是三元表示式x if condition else y的向量化版本 2 形式 np.where a,b,c 表示如果符合條件a則執行b否則執行c 二 數學和統計方法 np.random.randn 表示生成正態分佈的隨機數 部分函...
在SQLMAP中使用動態SQL
最近有幾個同事和朋友詢問如何在sqlmap中 拼接字串 因為有時候條件的數量不固定,條件引數型別也不固定,無法寫出 引數名 這樣的sql語句,也就是大家常說的 動態sql 問題。pdf.net資料開發框架在1.0版本就支援這個功能了,而且在sqlmap說明裡面也寫了,但就是沒有人看 這裡舉乙個實際的...
在SQLMAP中使用動態SQL
最近有幾個同事和朋友詢問如何在sqlmap中 拼接字串 因為有時候條件的數量不固定,條件引數型別也不固定,無法寫出 引數名 這樣的sql語句,也就是大家常說的 動態sql 問題。pdf.net資料開發框架在1.0版本就支援這個功能了,而且在sqlmap說明裡面也寫了,但就是沒有人看 這裡舉乙個實際的...