提问人:caesar753 提问时间:4/10/2023 最后编辑:caesar753 更新时间:4/11/2023 访问量:65
将 dtype 分配给 numpy 数组的每个列
assign a dtype to each colum of a numpy array
问:
我正在尝试为 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']
评论
groups = np.split(array['A'], np.cumsum(np.unique(array['A'], return_counts=True)[1])[:-1])
compound dtype
dt
structured array
groups
将数据放在数组中后,就可以轻松计算字段(列)的平均值和标准差。此答案显示了如何扩展上面@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
为了方便复制粘贴,我用字符串列表代替您的文件:
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 索引不起作用。一般来说,你不能跨领域做数学运算。
可以定义一个将 3 个浮点列组合在一起的 dtype:
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]])
或者将所有数值列加载为浮点数,跳过字符串列。这给出了 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
- 从文件 .txt 创建数组后,我使用 argsort 和 astype(int) for array[:,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()]
- 然后我对 array[:,1] 进行操作,使用 .astype(float) 计算平均值和 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])
- 然后我将 group_stats 用于其他事情(我必须选择累积置信水平 >0.35 且标准偏差 < 0.2) 的 3 个类
评论
'posizioni_mm.txt'
print([([x for x in line.split()]) for line in f])
array =
, then the
, or
arr['BCD']
loadtxt
或 with ,将自动推断字段 dtypes。您仍然可以获得一维结构数组。另一个想法是用于加载除最后一列(字符串一列)之外的所有列。其余的可以加载为浮点数,您可以自由地进行“数学运算”genfromtxt
dtype=None
usecols