在recarray中自动字符串长度
如果我这样创建一个记录数组:
In [29]: np.rec.fromrecords([(1,'hello'),(2,'world')],names=['a','b'])
结果看起来不错:
Out[29]:
rec.array([(1, 'hello'), (2, 'world')],
dtype=[('a', '<i8'), ('b', '|S5')])
但是如果我想指定数据类型:
In [32]: np.rec.fromrecords([(1,'hello'),(2,'world')],dtype=[('a',np.int8),('b',np.str)])
字符串的长度被设置为零:
Out[32]:
rec.array([(1, ''), (2, '')],
dtype=[('a', '|i1'), ('b', '|S0')])
我需要为所有数字类型指定数据类型,因为我关心的是 int8、int16、int32 等等,但我又想利用自动检测字符串长度的功能,这个功能在我不指定数据类型时可以正常工作。我试着把 np.str 替换成 None,但没有成功。我知道我可以指定 '|S5' 这样的格式,但我不知道字符串的长度应该设置成多少。
2 个回答
0
我不知道怎么让numpy帮你判断某些数据类型的特性,而不去判断其他的。不过你可以试试,比如:
data = [(1,'hello'),(2,'world')]
dlen = max(len(s) for i, s in data)
st = '|S%d' % dlen
np.rec.fromrecords(data, dtype=[('a',np.int8), ('b',st)])
2
如果你不需要把字符串当作字节来处理,可以用对象数据类型来表示它们。这样做其实是存储一个指针,而不是实际的字节内容:
In [38]: np.array(data, dtype=[('a', np.uint8), ('b', np.object)])
Out[38]:
array([(1, 'hello'), (2, 'world')],
dtype=[('a', '|u1'), ('b', '|O8')])
另外,Alex的想法也很好:
new_dt = []
# For each field of a given type and alignment, determine
# whether the field is an integer. If so, represent it as a byte.
for f, (T, align) in dt.fields.iteritems():
if np.issubdtype(T, int):
new_dt.append((f, np.uint8))
else:
new_dt.append((f, T))
new_dt = np.dtype(new_dt)
np.array(data, dtype=new_dt)
这样应该会得到
array([(1, 'hello'), (2, 'world')],
dtype=[('f0', '|u1'), ('f1', '|S5')])