我有两个2D numpy数组,一个用于纬度,另一个用于经度。
a = [ [1, 2, 3, 4], b = [ [a, b, c, d],
[1, 2, 3, 4], [a, b, c, d],
[1, 2, 3, 4], [a, b, c, d],
[1, 2, 3, 4] ] [a, b, c, d] ]
我想要以下2种输出(一个列表和一个2D元组数组)
output1 = [ (1,a), (2,a), (3,a), (4,a), (1,b), (2,b), (3,b), (4,b), . . . (3,d), (4,d) ]
output2 = [ [(1,a), (2,a), (3,a), (4,a)],
[(1,b), (2,b), (3,b), (4,b)],
[(1,c), (2,c), (3,c), (4,c)],
[(1,d), (2,d), (3,d), (4,d)] ]
我应该如何有效地做到无循环?
这是 a 和 b 生成的代码:
aa = np.array([1,2,3,4])
bb = np.array(['a','b','c','d'])
a, b = np.meshgrid(aa,bb)
答案 0 :(得分:2)
不带numpy的解决方案
from itertools import chain
output2 = [list(zip(i,j)) for i,j in zip(a,zip(*b))]
output1 = list(chain.from_iterable(output2))
答案 1 :(得分:1)
您的2个数组:
In [88]: aa = np.array([1,2,3,4])
...: bb = np.array(['a','b','c','d'])
...: a, b = np.meshgrid(aa,bb)
In [89]: a
Out[89]:
array([[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]])
In [90]: b
Out[90]:
array([['a', 'a', 'a', 'a'],
['b', 'b', 'b', 'b'],
['c', 'c', 'c', 'c'],
['d', 'd', 'd', 'd']], dtype='<U1')
某些版本的concatenate
可用于连接两个数组。 stack
和第2轴一起完成,np.array((a,b))
也跟着转置。
In [91]: np.stack((a,b),axis=2)
Out[91]:
array([[['1', 'a'],
['2', 'a'],
['3', 'a'],
['4', 'a']],
[['1', 'b'],
['2', 'b'],
['3', 'b'],
['4', 'b']],
[['1', 'c'],
['2', 'c'],
['3', 'c'],
['4', 'c']],
[['1', 'd'],
['2', 'd'],
['3', 'd'],
['4', 'd']]], dtype='<U21')
但是组合数组是字符串dtype,而不是整数和字符串的混合。而不是元组。这是一个(4,4,2)数组。
但是如果我们将数组转换为对象dtype:
In [93]: np.stack((a.astype(object),b.astype(object)),axis=2)
Out[93]:
array([[[1, 'a'],
[2, 'a'],
[3, 'a'],
[4, 'a']],
[[1, 'b'],
[2, 'b'],
...
[4, 'd']]], dtype=object)
我们可以将其重塑为(-1,2),然后tolist()
以产生列表版本。
或者我们可以创建一个结构化的数组,其中包含一个整数字段和一个字符串字段。其打印显示使用元组标记内部记录(与上面的最后一个大小2维不同)。
In [98]: arr = np.zeros(a.shape, dtype='int,U5')
In [99]: arr
Out[99]:
array([[(0, ''), (0, ''), (0, ''), (0, '')],
[(0, ''), (0, ''), (0, ''), (0, '')],
[(0, ''), (0, ''), (0, ''), (0, '')],
[(0, ''), (0, ''), (0, ''), (0, '')]],
dtype=[('f0', '<i8'), ('f1', '<U5')])
In [100]: arr['f0']=a
In [101]: arr['f1']=b
In [102]: arr
Out[102]:
array([[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')],
[(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')],
[(1, 'c'), (2, 'c'), (3, 'c'), (4, 'c')],
[(1, 'd'), (2, 'd'), (3, 'd'), (4, 'd')]],
dtype=[('f0', '<i8'), ('f1', '<U5')])
In [103]: print(arr)
[[(1, 'a') (2, 'a') (3, 'a') (4, 'a')]
[(1, 'b') (2, 'b') (3, 'b') (4, 'b')]
[(1, 'c') (2, 'c') (3, 'c') (4, 'c')]
[(1, 'd') (2, 'd') (3, 'd') (4, 'd')]]
zip
列表理解可以很好地完成列表版本:
In [105]: [item for item in zip(a.flat,b.flat)]
Out[105]:
[(1, 'a'),
(2, 'a'),
(3, 'a'),
(4, 'a'),
(1, 'b'),
...
(4, 'd')]
对于此样本大小,列表理解速度更快。尝试避免循环并不总是最有效的方法。
===
arr
的元素是np.void
对象,尽管它们显示为元组。要获取实际的元组,我们必须将其转换为list或object dtype:
In [109]: arr.tolist()
Out[109]:
[[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')],
[(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')],
[(1, 'c'), (2, 'c'), (3, 'c'), (4, 'c')],
[(1, 'd'), (2, 'd'), (3, 'd'), (4, 'd')]]
In [110]: arr.astype(object)
Out[110]:
array([[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')],
[(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')],
[(1, 'c'), (2, 'c'), (3, 'c'), (4, 'c')],
[(1, 'd'), (2, 'd'), (3, 'd'), (4, 'd')]], dtype=object)
In [111]: type(_[0,0])
Out[111]: tuple
可以通过名称访问结构化数组的字段:
In [112]: arr['f0']
Out[112]:
array([[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]])
答案 2 :(得分:0)
使用numpy和tolist
的矢量化方法:
a = np.array([[1,2,3,4],
[1,2,3,4],
[1,2,3,4],
[1,2,3,4]])
b = np.array([[10,20,30,40],
[10,20,30,40],
[10,20,30,40],
[10,20,30,40]])
x = np.stack((a,b), axis=-1)
x.reshape(4,4,2).tolist()
[[[1, 10], [2, 10], [3, 10], [4, 10]],
[[1, 20], [2, 20], [3, 20], [4, 20]],
[[1, 30], [2, 30], [3, 30], [4, 30]],
[[1, 40], [2, 40], [3, 40], [4, 40]]]
x.reshape(16,2).tolist()
[[1, 10], [2, 10], [3, 10], [4, 10], [1, 20], [2, 20], [3, 20], [4, 20], [1, 30], [2, 30], [3, 30], [4, 30], [1, 40], [2, 40], [3, 40], [4, 40]]