2015-07-19 333 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)和适当的选项会更好。它可以生成适当的元组列表,并直接返回结构化数组。

相关问题