在NumPy中使用動態陣列

2021-06-19 16:47:27 字數 3761 閱讀 3987

本文**:

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

()

程式的輸出如下圖所示,圖中每個階梯跳變的位置都表示一次記憶體分配,而每個階梯的高度表示額外分配的記憶體的大小。

import

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

()

python標準庫中的array陣列也提供了動態分配記憶體的功能,而且它和numpy陣列一樣直接將數值的二進位制資料儲存在一塊記憶體中,因此我們可以先用array陣列收集陣列,然後通過np.frombuffer()將array陣列的資料記憶體直接轉換為乙個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陣列中的第乙個元素也同時改變

array陣列只支援一維,如果我們需要採集多個頻道的資料,可以將這些資料依次新增進array陣列,然後通過reshape()方法將np.frombuffer()所建立的numpy陣列改為二維陣列。下面是乙個例子:

buf

=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

在這個例子中,❶我們通過array陣列buf採集兩個頻道的資料,資料採集完畢之後,我們通過np.frombuffer()將其轉換為numpy陣列,並通過reshape()將其形狀改為(100,2)。

當每個頻道的資料型別不同時,就不能採用上節所介紹的方法了。這時我們可以使用bytearray收集資料。bytearray是位元組陣列,因此我們首先需要通過struct模組將python的數值轉換成其位元組表示形式。如果資料來自二進位制檔案或者硬體,那麼我們得到得已經是位元組資料,這個步驟可以省略。下面是使用bytearray進行資料採集的例子:

buf

=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)❸

print

data

❶採集三個頻道的資料,其中頻道1是短整型整數,其型別符號為」h」,頻道2和3為雙精度浮點數,其型別符號為」d」。型別格式字串中的」=」表示輸出得位元組資料不進行記憶體對齊。即一條資料的位元組數為2+8+8=16,如果沒有」=」,那麼一條資料的位元組數則為8+8+8=24。

❷定義乙個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說明裡面也寫了,但就是沒有人看 這裡舉乙個實際的...