我在numpy中很难理解结构数组。
假设我有
- 两个元组列表(使用本地python类型)。
foo_list
和bar_list
. -
len(foo_list)==len(bar_list)
列表长度相同 - 对于所有i,j:
len(foo_list[i])==len(foo_list[j])
和len(bar_list[i])==len(bar_list[j])
,每个列表中的元组都是相同的长度。但是这些长度直到运行时才知道(所以我不能硬编码成dtype字符串) - for all i,j:
len(foo_list[i])!=len(bar_list[j])
不同list中的元组有不同的长度
我如何压缩这两个一起成结构数组?
在我自己检查结构之后,指定dtype似乎会涉及到大量的字符串操作。我确实试过一次,它不是很好的代码,所以我想一定有一个更好的方法来做到这一点。
目前我正在做:目前我的解决方案是将它们压缩并传递给numpy.asarray
,但这会产生奇怪的结果。它创建了一个对象的二维数组这些对象就是数组。如果你把它切片,你会得到一个数组的数组——而不是一个二维数组。
示例数据:
foo_list = [(0.0, 1.0, 1.0, 0.0, 1.0),
(1.0, 0.0, 1.0, 0.0, 1.0),
(1.0, 1.0, 1.0, 0.0, 0.0),
(0.0, 0.0, 0.0, 0.0, 1.0),
(0.0, 1.0, 1.0, 1.0, 0.0),
(1.0, 1.0, 1.0, 0.0, 1.0),
(0.0, 0.0, 0.0, 0.0, 0.0),
(0.0, 0.0, 0.0, 1.0, 0.0),
(1.0, 1.0, 1.0, 1.0, 0.0),
(1.0, 0.0, 0.0, 1.0, 0.0)]
bar_list = [(0.56885990540494535, 0.54212235514533669),
(-1.0024727291757354, 0.75636919036826),
(1.0912423038752346, 0.66209493674389353),
(0.52256034116805239, 0.36499434352207855),
(-1.6837689312941191, 0.90001803836488747),
(-3.1590090289110528, -0.3383410738003263),
(1.4080085734609102, -1.6283826051481185),
(1.5037872498731264, 1.5673560444854553),
(-2.271232989935922, 0.24542353558497185),
(-1.9752557923680221, 0.07968567723276497)]
您可以创建一个结构化数组,其中每个结构都有两个字段,"foo"one_answers"bar"。每个字段是一个一维数组。下面是创建这样一个结构化数组的一种方法。
首先获取"foo"one_answers"bar"字段的长度:
In [26]: nfoo = len(foo_list[0])
In [27]: nbar = len(bar_list[0])
为结构化数组创建dtype
。它有两个字段,"foo"one_answers"bar"。每个字段将包含一个浮点值数组,长度分别为nfoo
和nbar
。
In [28]: dt = np.dtype([('foo', np.float64, nfoo), ('bar', np.float64, nbar)])
用np.array
创建数组,给它压缩列表和新的dtype。
In [29]: a = np.array(zip(foo_list, bar_list), dtype=dt)
a
是一个长度为10的一维数组:
In [30]: a.shape
Out[30]: (10,)
In [31]: a
Out[31]:
array([([0.0, 1.0, 1.0, 0.0, 1.0], [0.5688599054049454, 0.5421223551453367]),
([1.0, 0.0, 1.0, 0.0, 1.0], [-1.0024727291757354, 0.75636919036826]),
([1.0, 1.0, 1.0, 0.0, 0.0], [1.0912423038752346, 0.6620949367438935]),
([0.0, 0.0, 0.0, 0.0, 1.0], [0.5225603411680524, 0.36499434352207855]),
([0.0, 1.0, 1.0, 1.0, 0.0], [-1.683768931294119, 0.9000180383648875]),
([1.0, 1.0, 1.0, 0.0, 1.0], [-3.159009028911053, -0.3383410738003263]),
([0.0, 0.0, 0.0, 0.0, 0.0], [1.4080085734609102, -1.6283826051481185]),
([0.0, 0.0, 0.0, 1.0, 0.0], [1.5037872498731264, 1.5673560444854553]),
([1.0, 1.0, 1.0, 1.0, 0.0], [-2.271232989935922, 0.24542353558497185]),
([1.0, 0.0, 0.0, 1.0, 0.0], [-1.975255792368022, 0.07968567723276497])],
dtype=[('foo', '<f8', (5,)), ('bar', '<f8', (2,))])
我们可以用很多方法来分割a
。
a['foo']
是来自foo_list
的整个二维数组:
In [32]: a['foo']
Out[32]:
array([[ 0., 1., 1., 0., 1.],
[ 1., 0., 1., 0., 1.],
[ 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 1.],
[ 0., 1., 1., 1., 0.],
[ 1., 1., 1., 0., 1.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 1., 0.],
[ 1., 1., 1., 1., 0.],
[ 1., 0., 0., 1., 0.]])
a['bar'][0, -1]
是bar_list
第一行的最后一列:
In [33]: a['bar'][0,-1]
Out[33]: 0.54212235514533669
a[0]['bar']
是bar_list
的第一行。(这也可以作为a['bar'][0]
访问)。
In [34]: a[0]['bar']
Out[34]: array([ 0.56885991, 0.54212236])
因为"foo"one_answers"bar"字段中的单个数据元素都是np.float64
类型的,所以您可以创建该数据的二维视图。下面,v
是形状为(10,7)的二维数组。
In [42]: v = a.view(np.float64).reshape(len(a), -1)
In [43]: v.shape
Out[43]: (10, 7)
In [44]: v[0]
Out[44]:
array([ 0. , 1. , 1. , 0. , 1. ,
0.56885991, 0.54212236])
In [45]: v[0, -1]
Out[45]: 0.54212235514533669
但是如果你想要一个二维数组,你不需要创建一个结构化数组数组中。您可以通过几种方式直接创建二维数组。例如,
In [46]: b = np.array([f+b for f, b in zip(foo_list, bar_list)])
In [47]: b.shape
Out[47]: (10, 7)
In [48]: b[0]
Out[48]:
array([ 0. , 1. , 1. , 0. , 1. ,
0.56885991, 0.54212236])
In [49]: b[0, -1]
Out[49]: 0.54212235514533669