为numpy数组的每一列指定一个dtype



我试图为numpy数组的每列转换dtype,但我没有运气。我尝试了一些解决方案在stackoverflow上找到(例如使用astype()函数为每个列,如这里或试图显式声明np.array(..., dtype = [])的数据类型,如这里建议,但没有工作…

特别是对于第二个解决方案,如果我尝试这个代码

with open('posizioni_mm.txt') as f:
a, b, c, d, e  = [x for x in next(f).split()]

dt = [('A', 'int'), ('B', 'float'), ('C', 'float'), ('D', 'float'), ('E', '<U32')]
array = np.array([([x for x in line.split()]) for line in f], dtype = dt )

我得到这个错误

ValueError: could not convert string to float: 'link_2'

作为数组移位一列('link_2'应该是列E,它的dtype应该是字符串,但它被放在列D),如果我试图生成没有数据类型的数组,然后是一个空数组与正确的dtypes

array2 = np.zeros(np.shape(array), dtype = dt)

生成一个包含5个元组的数组,每行5个元素

[[(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, 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., 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., 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., '')
(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, 0., 0., 0., '') (0, 0., 0., 0., '')
(0, 0., 0., 0., '') (0, 0., 0., 0., '')]]

怎么了?

编辑:这是posizioni_mm.txt文件的内容

30 0.78 227.31 270.7 link_1
30 0.73 310.79 268.72 link_2
30 0.32 141.41 276.87 link_3
35 0.45 72.47 212.11 link_4
30 0.18 163.22 205.95 link_5
8 0.25 109.69 207.49 link_6
24 0.3 295.15 197.14 link_7
45 0.3 390.97 179.96 link_8
8 0.45 153.08 101.1 link_9
33 0.36 87.44 114.32 link_10
8 0.24 285.9 94.27 link_11
30 0.42 326.87 90.97 link_12
33 0.4 221.15 96.92 link_13
18 0.2 257.49 56.61 link_14
51 0.16 194.71 53.96 link_15

使用numpy.loadtxt从文本文件中简单加载数据:

with open('posizioni_mm.txt') as f:
dt = [('A', 'int'), ('B', 'float'), ('C', 'float'), ('D', 'float'), ('E', '<U32')]
arr = np.loadtxt(f, dtype=dt)
print(arr)

[(30, 0.78, 227.31, 270.7 , 'link_1') (30, 0.73, 310.79, 268.72, 'link_2')
(30, 0.32, 141.41, 276.87, 'link_3') (35, 0.45,  72.47, 212.11, 'link_4')
(30, 0.18, 163.22, 205.95, 'link_5') ( 8, 0.25, 109.69, 207.49, 'link_6')
(24, 0.3 , 295.15, 197.14, 'link_7') (45, 0.3 , 390.97, 179.96, 'link_8')
( 8, 0.45, 153.08, 101.1 , 'link_9')
(33, 0.36,  87.44, 114.32, 'link_10')
( 8, 0.24, 285.9 ,  94.27, 'link_11')
(30, 0.42, 326.87,  90.97, 'link_12')
(33, 0.4 , 221.15,  96.92, 'link_13')
(18, 0.2 , 257.49,  56.61, 'link_14')
(51, 0.16, 194.71,  53.96, 'link_15')]

现在您可以通过名称访问列,例如:'E':


print(arr['E'])

['link_1' 'link_2' 'link_3' 'link_4' 'link_5' 'link_6' 'link_7' 'link_8'
'link_9' 'link_10' 'link_11' 'link_12' 'link_13' 'link_14' 'link_15']

一旦您将数据放入数组中,就很容易计算字段(列)的平均值和标准差。这个答案展示了如何扩展上面由@RomanPerekhrest发布的解决方案。

f = 'posizioni_mm.txt'
dt = [('A', 'int'), ('B', 'float'), ('C', 'float'), ('D', 'float'), ('E', '<U32')]
arr = np.loadtxt(f, dtype=dt)
col_B = arr['B'] # to load column B values to an array
print(f"Col B mean = {np.mean(col_B):.2f}") # reference col_B above
print(f"Col B stddev = {np.std(arr['B']):.2f}") # Or just use arr['B']

数据的打印值:

Col B mean = 0.37
Col B stddev = 0.18

为了便于复制-n-粘贴,我为您的文件替换了一个字符串列表:

In [27]: txt = """30 0.78 227.31 270.7 link_1
...: 30 0.73 310.79 268.72 link_2
...: 30 0.32 141.41 276.87 link_3
...: 35 0.45 72.47 212.11 link_4
...: 30 0.18 163.22 205.95 link_5""".splitlines()

您的复合类型:

In [28]: dt = [('A', 'int'), ('B', 'float'), ('C', 'float'), ('D', 'float'), ('E', '<U32')]

要从数据创建一个结构化数组,需要提供一个元组列表(而不是列表的列表)。只需稍微修改一下代码就可以了:

In [29]: np.array([(tuple([x for x in line.split()])) for line in txt], dtype = dt )
Out[29]: 
array([(30, 0.78, 227.31, 270.7 , 'link_1'),
(30, 0.73, 310.79, 268.72, 'link_2'),
(30, 0.32, 141.41, 276.87, 'link_3'),
(35, 0.45,  72.47, 212.11, 'link_4'),
(30, 0.18, 163.22, 205.95, 'link_5')],
dtype=[('A', '<i4'), ('B', '<f8'), ('C', '<f8'), ('D', '<f8'), ('E', '<U32')])

loadtxt/genfromtxt:

也是一样
In [30]: data = np.loadtxt(txt,dtype=dt)    
In [31]: data
Out[31]: 
array([(30, 0.78, 227.31, 270.7 , 'link_1'),
(30, 0.73, 310.79, 268.72, 'link_2'),
(30, 0.32, 141.41, 276.87, 'link_3'),
(35, 0.45,  72.47, 212.11, 'link_4'),
(30, 0.18, 163.22, 205.95, 'link_5')],
dtype=[('A', '<i4'), ('B', '<f8'), ('C', '<f8'), ('D', '<f8'), ('E', '<U32')])
In [35]: data['A']
Out[35]: array([30, 30, 30, 35, 30])

我不知道你想用小组做什么。请记住,对于结构化数组,您拥有字段,而不是列。所以2d索引不起作用。一般来说,你不能跨领域做数学运算。

可以定义一个dtype,将3个float列组合在一起:

In [36]: dt = [('A', 'int'), ('BCD', 'float',3), ('E', '<U32')]    
In [37]: data = np.loadtxt(txt,dtype=dt)    
In [38]: data
Out[38]: 
array([(30, [7.8000e-01, 2.2731e+02, 2.7070e+02], 'link_1'),
(30, [7.3000e-01, 3.1079e+02, 2.6872e+02], 'link_2'),
(30, [3.2000e-01, 1.4141e+02, 2.7687e+02], 'link_3'),
(35, [4.5000e-01, 7.2470e+01, 2.1211e+02], 'link_4'),
(30, [1.8000e-01, 1.6322e+02, 2.0595e+02], 'link_5')],
dtype=[('A', '<i4'), ('BCD', '<f8', (3,)), ('E', '<U32')])        
In [40]: data['BCD']
Out[40]: 
array([[7.8000e-01, 2.2731e+02, 2.7070e+02],
[7.3000e-01, 3.1079e+02, 2.6872e+02],
[3.2000e-01, 1.4141e+02, 2.7687e+02],
[4.5000e-01, 7.2470e+01, 2.1211e+02],
[1.8000e-01, 1.6322e+02, 2.0595e+02]])

或者将所有数值列加载为float,跳过字符串列。这给出了2d浮点数组:

In [41]: data = np.genfromtxt(txt,usecols=[0,1,2,3],encoding=None)
In [42]: data
Out[42]: 
array([[3.0000e+01, 7.8000e-01, 2.2731e+02, 2.7070e+02],
[3.0000e+01, 7.3000e-01, 3.1079e+02, 2.6872e+02],
[3.0000e+01, 3.2000e-01, 1.4141e+02, 2.7687e+02],
[3.5000e+01, 4.5000e-01, 7.2470e+01, 2.1211e+02],
[3.0000e+01, 1.8000e-01, 1.6322e+02, 2.0595e+02]])

感谢大家,我用一种非常不优雅的方式解决了这个问题,但是…它是

简而言之,我大量使用。astype(…)方法将字符串(暂时)转换为int或float
  1. 从文件。txt创建数组后,我使用argsort与astype(int)为数组[:,0]
with open(file) as f:

array = np.array([[x for x in line.split()] for line in f])
array = array[array[:, 0].astype(int).argsort()]
  1. 则I对数组[:,1]进行操作,使用.astype(float)
  2. 计算平均值和std
groups = np.split(array[:, 0:], np.cumsum(np.unique(array[:, 0].astype(int), return_counts=True)[1])[:-1])
group_stats = np.array([(g[0, 0], len(g), np.mean(g[:, 1].astype(float)).round(2), np.std(g[:, 1].astype(float)).round(2)) for g in groups])
  1. 然后我使用group_stats用于其他事情(我必须选择具有累积置信水平>0.35和标准偏差<0.2)

相关内容

最新更新