2015-07-19 55 views
2

我有一個存儲在NumPy數組中的數據集,如下所示,但其中的所有數據都以字符串形式存儲。如何將字符串更改爲intfloat,並將其存儲回去?如何將NumPy數組元素從字符串更改爲int或float?

data = numpy.array([]) # <--- array initialized with numpy.array 
data可變

,以下信息被存儲

[['1' '0' '3' ..., '7.25' '' 'S'] 
    ['2' '1' '1' ..., '71.2833' 'C85' 'C'] 
    ['3' '1' '3' ..., '7.925' '' 'S'] 
    ..., 
    ['889' '0' '3' ..., '23.45' '' 'S'] 
    ['890' '1' '1' ..., '30' 'C148' 'C'] 
    ['891' '0' '3' ..., '7.75' '' 'Q']] 

我想改變的第一列到int和存儲值回來。爲此,我做了:

data[0::,0] = data[0::,0].astype(int) 

但是,它沒有改變任何東西。

+0

你的意思是複述http://docs.scipy.org/doc/numpy/reference/generated/numpy.recarray.html? –

+0

'['''''''''''','7.25'''''''']'從哪裏來的呢? –

+0

'data'的形狀和dtype是什麼? – hpaulj

回答

2

您可以將數據類型(dtype)設置爲array初始化。例如,如果您的行由一個32位整數和一個4字節的字符串組成,您可以指定dtype 'i4, S4'

data = np.array([(1, 'a'), (2, 'b')], dtype='i4, S4') 

你可以閱讀更多關於dtypes here

+0

這是幹什麼的? –

+0

@PadraicCunningham您指定每行的數據類型(dtype)是一個4字節的整數和一個4字節的字符串。 –

+0

我沒有要求自己,我已經在評論中發佈了一個鏈接。 OP的一些解釋以及他/她如何將原始數據對象轉換爲第一列作爲整數的數組將是很好的。 –

0

NumPy數組具有其元素的關聯類型。分配一個NumPy數組的片段會將新數據上傳到該類型。如果這是不可能的,任務將失敗,異常:

import numpy 
a = numpy.array([[1, 2],[3, 4]]) 
print a 
# [[1 2] 
# [3 4]] 
print a.dtype 
# int64 

a[0,0] = 'look, a string' 
# ValueError: invalid literal for long() with base 10: 'a' 

在你的情況,data[0::,0].astype(int)會產生與NumPy陣列與相關聯的成員類型int64,但分配放回原數組的一個切片將其轉換回字符串。

除了標準的NumPy陣列,Padraic's comment中提到的NumPy record arrays允許不同列的不同類型。

我不知道,如果一個標準的NumPy的陣列可以轉換爲就地一NumPy的記錄陣列,所以在構建答案enrico's建議一個像

data = np.array([(1, 'a'), (2, 'b')], dtype='i4, S4') 

可能是最好的選擇。如果這是不可能的,你可以從你的標準與NumPy陣列構建一個與結果覆蓋變量:

import numpy 
data = numpy.array([['1', '0', '3', '7.25', '', 'S'], 
        ['2', '1', '1', '71.2833', 'C85', 'C'], 
        ['3', '1', '3', '7.925', '', 'S'], 
        ['889', '0', '3', '23.45', '', 'S'], 
        ['890', '1', '1', '30', 'C148', 'C'], 
        ['891', '0', '3', '7.75', '', 'Q']]) 
print(repr(data)) 
# array([['1', '0', '3', '7.25', '', 'S'], 
#  ['2', '1', '1', '71.2833', 'C85', 'C'], 
#  ['3', '1', '3', '7.925', '', 'S'], 
#  ['889', '0', '3', '23.45', '', 'S'], 
#  ['890', '1', '1', '30', 'C148', 'C'], 
#  ['891', '0', '3', '7.75', '', 'Q']], 
#  dtype='|S7') 

data = numpy.core.records.fromarrays(data.T, dtype='i4,S4,S4,S4,S4,S4') 
print(repr(data)) 
# rec.array([(1, '0', '3', '7.25', '', 'S'), (2, '1', '1', '71.2', 'C85', 'C'), 
#  (3, '1', '3', '7.92', '', 'S'), (889, '0', '3', '23.4', '', 'S'), 
#  (890, '1', '1', '30', 'C148', 'C'), (891, '0', '3', '7.75', '', 'Q')], 
#  dtype=[('f0', '<i4'), ('f1', '|S4'), ('f2', '|S4'), ('f3', '|S4'), ('f4', '|S4'), ('f5', '|S4')]) 
+0

有人知道是否可以進行就地轉換,或者如何從標準的NumPy數組構建記錄數組? @PadraicCunningham,也許? –

+0

不確定就地,但如果數據是一個Python列表的列表,你可以'np.array(list(map(tuple,data)),dtype =「i4,S4,S4,S4,S4,S4」),if它是一個數組,你可以'np.core.records.fromarrays(data.T,dtype =「i4,S4,S4,S4,S4,S4」))' –

+0

就地轉換必須保持總數據緩衝區大小不變。 'i4'dtypes可以改變爲4'i1'類型,或者(我認爲)4's1'。但是將字符串解釋爲整數或浮點數將會改變字節數,並且不能在原地完成。 – hpaulj

0

我可以通過對字符串列表的開始包含字符串數組;注意S4 D型:

In [690]: data=np.array([['1','0','7.23','two'],['2','3','1.32','four']]) 

In [691]: data 
Out[691]: 
array([['1', '0', '7.23', 'two'], 
     ['2', '3', '1.32', 'four']], 
     dtype='|S4') 

它更可能通過讀取CSV文件,這樣一種陣列創建。

我也可以認爲它是單字節字符串數組 - 的形狀和D型細胞發生了變化,但對應於DataBuffer是相同的(相同的32個字節)

In [692]: data.view('S1') 
Out[692]: 
array([['1', '', '', '', '0', '', '', '', '7', '.', '2', '3', 't', 'w', 
     'o', ''], 
     ['2', '', '', '', '3', '', '', '', '1', '.', '3', '2', 'f', 'o', 
     'u', 'r']], 
     dtype='|S1') 

事實上,我可以改變單個字節,改變原始數組的twotwos

In [693]: data.view('S1')[0,-1]='s' 

In [694]: data 
Out[694]: 
array([['1', '0', '7.23', 'twos'], 
     ['2', '3', '1.32', 'four']], 
     dtype='|S4') 

但是,如果我嘗試的data的元素改變爲一個整數,它被轉換成一個字符串匹配S4 D型:

In [695]: data[1,0]=4 

In [696]: data 
Out[696]: 
array([['1', '0', '7.23', 'twos'], 
     ['4', '3', '1.32', 'four']], 
     dtype='|S4') 

如果數字來自int(data[1,0])或者其中的一些變化,也會發生同樣的情況。

但我可以欺騙成看到整數作爲字節串(表示爲\x04

In [704]: data[1,0]=np.array(4).view('S4') 

In [705]: data 
Out[705]: 
array([['1', '0', '7.23', 'twos'], 
     ['\x04', '3', '1.32', 'four']], 
     dtype='|S4') 

陣列可以共享數據緩衝器。 data屬性是指向一塊內存的指針。數組的dtype控制着該塊的解釋方式。例如,我可以讓整數的另一個數組,並重定向它的data屬性:

In [714]: d2=np.zeros((2,4),dtype=int) 

In [715]: d2 
Out[715]: 
array([[0, 0, 0, 0], 
     [0, 0, 0, 0]]) 

In [716]: d2.data=data.data # change the data pointer 

In [717]: d2 
Out[717]: 
array([[  49,   48, 858926647, 1936684916], 
     [   4,   51, 842214961, 1920298854]]) 

現在d2[1,0]是整數4,但其他項目不可識別的,因爲他們被視爲整數字符串。這與通過int()函數傳遞它們不一樣。

我不建議將data這樣的指針改爲常規操作。搞砸事情很容易。我必須注意確保d2.nbytes爲32,與data相同。

因爲緩衝區是分片,的變化,以d2也出現在data(但顯示的根據不同的D型):

In [718]: d2[0,0]=3 

In [719]: data 
Out[719]: 
array([['\x03', '0', '7.23', 'twos'], 
     ['\x04', '3', '1.32', 'four']], 
     dtype='|S4') 

具有複雜D型的視圖做類似的東西:

In [723]: data.view('i4,i4,f,|S4') 
Out[723]: 
array([[(3, 48, 4.148588672592268e-08, 'twos')], 
     [(4, 51, 1.042967401332362e-08, 'four')]], 
     dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<f4'), ('f3', 'S4')]) 

注意4851也出現在d2。下一個float列無法識別。

這給出了一個想法,可以和不可以做'就地'。

但是爲了以有意義的方式獲取包含數字和字符串的數組,我最好構造一個新的結構化數組。也許最乾淨的方式是使用中間元組列表。

In [759]: dl=[tuple(i) for i in data.tolist()] 

In [760]: dl 
Out[760]: [('1', '0', '7.23', 'two'), ('2', '3', '1.32', 'four')] 

In [761]: np.array(dl,dtype='i4,i4,f,|S4') 
Out[761]: 
array([(1, 0, 7.230000019073486, 'two'), (2, 3, 1.3200000524520874, 'four')], 
     dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<f4'), ('f3', 'S4')]) 

所有這些字段佔用4個字節,所以nbytes是相同的。但個人價值觀已通過轉換器。我已經給出'np.array'自由轉換值,這與輸入和新的dtype一致。這比嘗試執行某種複雜的就地轉換要容易得多。

名單與數字和字符串的混合元組也會工作:

[(1, 0, 7.23, 'two'), (2, 3, 1.32, 'four')] 

結構陣列將顯示一個元組列表。在結構化數組文檔中,值總是以元組列表的形式輸入。

recarray也可以使用,但本質上這只是一個數組子類,它允許您以字段的形式訪問字段。

如果原始數組是從csv文件生成的,那麼使用np.genfromtxt(或loadtxt)和適當的選項會更好。它可以生成適當的元組列表,並直接返回結構化數組。

相關問題