我正在使用python实用程序从Tycho 2星级目录中获取数据。我正在处理的一个函数查询目录并返回给定星号id(或一组星id)的所有信息。
我目前正在通过遍历目录文件的行来执行此操作,然后尝试将该行解析为numpy结构化数组(如果已查询)。 (注意,如果有更好的方法可以让我知道,即使这不是这个问题的意思 - 我这样做是因为目录太大而无法将所有内容加载到内存中一次)
无论如何,一旦我确定了我想保留的记录,我就遇到了问题...我无法弄清楚如何将其解析为结构化数组。
例如,我想保留的记录是:
record = '0002 00038 1| | 3.64121230| 1.08701186| 14.1| -23.0| 69| 82| 1.8| 1.9|1968.56|1957.30| 3|1.0|3.0|0.9|3.0|12.444|0.213|11.907|0.189|999| | | 3.64117944| 1.08706861|1.83|1.73| 81.0|104.7| | 0.0'
现在,我正在尝试使用dtype解析为numpy结构化数组:
dform = [('starid', [('TYC1', int), ('TYC2', int), ('TYC3', int)]),
('pflag', str),
('starBearing', [('rightAscension', float), ('declination', float)]),
('properMotion', [('rightAscension', float), ('declination', float)]),
('uncertainty', [('rightAscension', int), ('declination', int), ('pmRA', float), ('pmDc', float)]),
('meanEpoch', [('rightAscension', float), ('declination', float)]),
('numPos', int),
('fitGoodness', [('rightAscension', float), ('declination', float), ('pmRA', float), ('pmDc', float)]),
('magnitude', [('BT', [('mag', float), ('err', float)]), ('VT', [('mag', float), ('err', float)])]),
('starProximity', int),
('tycho1flag', str),
('hipparcosNumber', str),
('observedPos', [('rightAscension', float), ('declination', float)]),
('observedEpoch', [('rightAscension', float), ('declination', float)]),
('observedError', [('rightAscension', float), ('declination', float)]),
('solutionType', str),
('correlation', float)]
这似乎应该是一件相当简单的事情,但我尝试的一切都会破坏......
我试过了:
np.genfromtxt(BytesIO(record.encode()),dtype=dform,delimiter=(' ','|'))
np.genfromtxt(BytesIO(record.encode()),dtype=dform,delimiter=(' ','|'),missing_values=' ',filling_values=None)
这两个都给了我
{TypeError}cannot perform accumulate with flexible type
这是没有意义的,因为它不应该做任何积累。
我也试过
np.array(re.split('\|| ',record),dtype=dform)
抱怨
{TypeError}a bytes-like object is required, not 'str'
和另一个变种
np.array([x.encode() for x in re.split('\|| ',record)],dtype=dform)
不会抛出错误,但也肯定没有返回正确的结果:
[ ((842018864, 0, 0), '', (0.0, 0.0), (0.0, 0.0), (0, 0, 0.0, 0.0), (0.0, 0.0), 0, (0.0, 0.0, 0.0, 0.0), ((0.0, 0.0), (0.0, 0.0)), 0, '', '', (0.0, 0.0), (0.0, 0.0), (0.0, 0.0), '', 0.0)...
那我该怎么做呢?我认为genfromtxt选项是要走的路(特别是因为偶尔可能会丢失数据)但我不明白为什么它不起作用。这是我必须自己编写解析器吗?
答案 0 :(得分:3)
对不起,这个答案很长很漫无目的,但这就是弄清楚发生了什么。特别是dtype的复杂性因其长度而隐藏。
当我尝试TypeError: cannot perform accumulate with flexible type
的列表时出现delimiter
错误。详细信息显示LineSplitter
中发生错误。没有详细说明,分隔符应该是一个字符(或默认的'空格')。
来自genfromtxt
文档:
delimiter:str,int或sequence,可选 用于分隔值的字符串。默认情况下,任何连续 空格充当分隔符。整数或整数序列 也可以作为每个字段的宽度提供。
genfromtxt
拆分器比.split
使用的字符串loadtxt
更强大,但不像re
拆分器那样通用。
对于{TypeError}a bytes-like object is required, not 'str'
,您为几个字段指定dtype 'str'
。这是字节字符串,其中record
是unicode字符串(在Py3中)。但是你已经意识到BytesIO(record.encode())
。
我喜欢用以下内容测试genfromtxt
个案例:
record = b'....'
np.genfromtxt([record], ....)
或者更好
records = b"""one line
tow line
three line
"""
np.genfromtxt(records.splitlines(), ....)
如果我让genfromtxt
推断字段类型,只使用一个分隔符,我会得到32个字段:
In [19]: A=np.genfromtxt([record],dtype=None,delimiter='|')
In [20]: len(A.dtype)
Out[20]: 32
In [21]: A
Out[21]:
array((b'0002 00038 1', False, 3.6412123, 1.08701186, 14.1, -23.0, 69, 82, 1.8, 1.9, 1968.56, 1957.3, 3, 1.0, 3.0, 0.9, 3.0, 12.444, 0.213, 11.907, 0.189, 999, False, False, 3.64117944, 1.08706861, 1.83, 1.73, 81.0, 104.7, False, 0.0),
dtype=[('f0', 'S12'), ('f1', '?'), ('f2', '<f8'), ('f3', '<f8'), ('f4', '<f8'), ... ('f26', '<f8'), ('f27', '<f8'), ('f28', '<f8'), ('f29', '<f8'), ('f30', '?'), ('f31', '<f8')])
当我们得到整个字节和分隔符问题时
np.array([x for x in re.split(b'\|| ',record)],dtype=dform)
确实在运行。我现在看到你的dform很复杂,有嵌套的复合字段。
但是要定义一个结构化数组,你可以给它一个记录列表,例如
np.array([(record1...), (record2...), ....], dtype([(field1),(field2 ),...]))
在这里,您尝试创建一条记录。我可以将你的列表包含在一个元组中,但是我得到的长度与dform
长度之间的不匹配,66 v 17.如果算上所有子字段dform
可能需要66个值,但我们可以'只需用一个元组就可以做到这一点。
我从来没有尝试过这样一个复杂的dtype
创建一个数组,所以我正在寻找方法让它工作。
In [41]: np.zeros((1,),dform)
Out[41]:
array([ ((0, 0, 0), '', (0.0, 0.0), (0.0, 0.0), (0, 0, 0.0, 0.0), (0.0, 0.0), 0, (0.0, 0.0, 0.0, 0.0), ((0.0, 0.0), (0.0, 0.0)), 0, '', '', (0.0, 0.0), (0.0, 0.0), (0.0, 0.0), '', 0.0)],
dtype=[('starid', [('TYC1', '<i4'), ('TYC2', '<i4'), ('TYC3', '<i4')]), ('pflag', '<U'), ('starBearing', [('rightAscension', '<f8'), ('declination', '<f8')]), ('properMotion', [('rightAscension', '<f8'), ('declination', '<f8')]), ('uncertainty', [('rightAscension', '<i4'), ('declination', '<i4'), ('pmRA', '<f8'), ('pmDc', '<f8')]), ('meanEpoch', ....('solutionType', '<U'), ('correlation', '<f8')])
In [64]: for name in A.dtype.names:
print(A[name].dtype)
....:
[('TYC1', '<i4'), ('TYC2', '<i4'), ('TYC3', '<i4')]
<U1
[('rightAscension', '<f8'), ('declination', '<f8')]
[('rightAscension', '<f8'), ('declination', '<f8')]
[('rightAscension', '<i4'), ('declination', '<i4'), ('pmRA', '<f8'), ('pmDc', '<f8')]
[('rightAscension', '<f8'), ('declination', '<f8')]
int32
[('rightAscension', '<f8'), ('declination', '<f8'), ('pmRA', '<f8'), ('pmDc', '<f8')]
[('BT', [('mag', '<f8'), ('err', '<f8')]), ('VT', [('mag', '<f8'), ('err', '<f8')])]
int32
<U1
<U1
[('rightAscension', '<f8'), ('declination', '<f8')]
[('rightAscension', '<f8'), ('declination', '<f8')]
[('rightAscension', '<f8'), ('declination', '<f8')]
<U1
float64
我统计了34个原始dtype字段。大多数是'标量',大约2-4个术语,一个具有更高的嵌套水平。
如果我用|
替换前两个分割空格,record.split(b'|')
会给我34个字符串。
让我们在genfromtxt
:
In [79]: np.genfromtxt([record],delimiter='|',dtype=dform)
Out[79]:
array(((2, 38, 1), '', (3.6412123, 1.08701186), (14.1, -23.0),
(69, 82, 1.8, 1.9), (1968.56, 1957.3), 3, (1.0, 3.0, 0.9, 3.0),
((12.444, 0.213), (11.907, 0.189)), 999, '', '',
(3.64117944, 1.08706861), (1.83, 1.73), (81.0, 104.7), '', 0.0),
dtype=[('starid', [('TYC1', '<i4'), ('TYC2', '<i4'), ('TYC3', '<i4')]),
('pflag', '<U'),
('starBearing', [('rightAscension', '<f8'), ('declination', '<f8')]),
('properMotion', [('rightAscension', '<f8'), ('declination', '<f8')]),
('uncertainty', [('rightAscension', '<i4'), ('declination', '<i4'), ('pmRA', '<f8'), ('pmDc', '<f8')]),
('meanEpoch', [('rightAscension', '<f8'), ('declination', '<f8')]),
('numPos', '<i4'),
('fitGoodness', [('rightAscension', '<f8'), ('declination', '<f8'), ('pmRA', '<f8'), ('pmDc', '<f8')]),
('magnitude', [('BT', [('mag', '<f8'), ('err', '<f8')]), ('VT', [('mag', '<f8'), ('err', '<f8')])]),
('starProximity', '<i4'), ('tycho1flag', '<U'), ('hipparcosNumber', '<U'),
('observedPos', [('rightAscension', '<f8'), ('declination', '<f8')]),
('observedEpoch', [('rightAscension', '<f8'), ('declination', '<f8')]),
('observedError', [('rightAscension', '<f8'), ('declination', '<f8')]), ('solutionType', '<U'), ('correlation', '<f8')])
这几乎看起来很合理。 genfromtxt
实际上可以在复合字段中拆分值。这就是我想用np.array()
尝试的东西。
因此,如果你得到分隔符和字节/ unicode,genfromtxt
可以处理这个混乱。