将文本转换为numpy数组
我需要一个函数,它将(非二进制)字符串作为输入并返回一个numpy数组。将文本转换为numpy数组
与NumPy提供了功能numpy.fromstring,这适用于所有的情况下(正确的参数):
>>> np.fromstring('1 2 3.1415', dtype=float, sep=' ')
array([ 1. , 2. , 3.1415])
我的问题是,它在许多情况下。例如,在下列情况下,它静静地失败
>>> np.fromstring('not a string', dtype=float, sep=' ')
array([], dtype=float64)
有没有办法安全地转换成非二进制字符串numpy的,妥善抛出一个错误,如果输入无法转换为数字阵列?
您可以直接与字符串工作,并使用np.array
和split
,像这样将其转换回numpy的数组:
>>> np.array('1 2 3.1415'.split(' '), dtype=float)
array([ 1. , 2. , 3.1415])
>>> np.array('not a string'.split(' '), dtype=float)
ValueError: could not convert string to float: not
当使用fromstring
,如果你输入的字符串不包含唯一的真正价值数据,你应该期望一个空数组。
>>> np.fromstring('not a string', dtype=float, sep=' ')
array([], dtype=float64)
>>> np.fromstring('not a string 5', dtype=float, sep=' ')
array([], dtype=float64)
>>> np.fromstring('8 5', dtype=float, sep=' ')
array([ 8., 5.])
编辑: 您可以实现自己的.fromstring
通过验证您的input_string
格式。如果它确实有你正在寻找的模式(在你的情况下所有浮动),然后将其转换为numpy.array
。如果发生故障,您要么显式地通过异常错误,要么返回空列表。
In [1]: import re
In [2]: import numpy as np
In [3]: def my_fromstring(input_string):
...: input_string = input_string.strip()
...: input_string = re.sub(' +', ' ', input_string)
...: float_pattern = '\d+\.d+|\d+'
...: verify_fn = lambda s: map(lambda x: re.match(float_pattern, x),
...: s.split(' '))
...: pattern_match_fn = lambda x: any(map(lambda x: True if x == None
...: else False, x))
...: res = verify_fn(input_string)
...: match = pattern_match_fn(res)
...: if not match:
...: return np.array(map(float, input_string.split(' ')))
...: else:
...: raise ValueError('Incorrect input format')
...:
您现在可以使用自定义功能进行检查:
In [4]: my_fromstring(' 7 5 8 3 ')
Out[4]: array([ 7., 5., 8., 3.])
In [5]: my_fromstring('not a string')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-67-88cd38f7ad26> in <module>()
----> 1 my_fromstring('not a string')
<ipython-input-65-e355cf28acb0> in my_fromstring(input_string)
10 return np.array(map(float, input_string.split(' ')))
11 else:
---> 12 raise ValueError('Incorrect input format')
13
ValueError: Incorrect input format
为什么不检查操作后数组是否为空并在出现错误时抛出错误?
def extract(s):
a = np.fromstring(s.strip(), dtype=float, sep=' ')
if a.size == 0 or a.size == 1 and len(str(a[0])) != len(s.strip()):
raise Exception('No numbers found')
return a
这会失败,请尝试'np.fromstring('not a string',dtype = float,sep ='')' –
如果空白是问题,我们可以在解析之前'去掉'字符串。查看更改。 – Farhan
好的更新,现在至少我不能让它失败,但是我们知道没有其他失败的情况吗? –
你可以写一个正则表达式,因为它不是一个非常复杂的语言; json spec显示浮点数的图表。为了让这些之间的任意换行符和空间会是什么样子:
[\s\n]*(?:-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][-+]?\d+)?[\s\n]*)*
打破了下来,我们有:
[\s\n]* leading ws (whitespace)
(?: [\s\n]+)* repeat with trailing ws
-?(?:0|[1-9]\d*) an integer, no leading 0s
(?:\.\d+)? opt. decimal part
(?:[eE][-+]?\d+) opt. base-10 exponent
使用与^
为创业的串并$
封闭为最终OF-字符串,例如
re.match(r'^[\s\n]*(?:-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][-+]?\d+)?[\s\n]*)*$',
'1 2 3.12345')
# returns a Match object
re.match(r'^[\s\n]*(?:-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][-+]?\d+)?[\s\n]*)*$',
'1, 2, 3.12345')
# returns None because we did not allow commas in the regex.
当然允许可选的逗号,右后可选的指数包括:,?
,可选的逗号;如果需要方括号或分号,那么也不会太难添加。还要考虑将“重复跟踪ws”部分中的*
更改为+
以强制该数组非空。
尝试'np.fromstring('not a string',dtype = float,sep ='')',这会返回'array([ - 1。])''。 –
如果你知道你的输入数据格式,你可以应用'strip'功能,你仍然可以得到想要的输出。 –
'np.array(s.split(),dtype = float)'如果不能将其中一个'words'转换为float,将会抛出一个错误。 – hpaulj