Python 将函数应用于元组数组
我有一个函数,我想应用于元组数组,我想知道是否有一种干净的方法来实现它 通常,我可以使用Python 将函数应用于元组数组,python,arrays,numpy,vector,Python,Arrays,Numpy,Vector,我有一个函数,我想应用于元组数组,我想知道是否有一种干净的方法来实现它 通常,我可以使用np.vectorize将函数应用于数组中的每个项,但是,在这种情况下,“每个项”是一个元组,因此numpy将数组解释为一个3d数组,并将函数应用于元组中的每个项 因此,我可以假设传入阵列是以下阵列之一: 元组 一维元组数组 二维元组数组 我可能可以编写一些循环逻辑,但它似乎最有可能具有更高效的功能,我不想重新发明轮子 这是一个例子。我试图将tuple\u converter函数应用于数组中的每个元组 arr
np.vectorize
将函数应用于数组中的每个项,但是,在这种情况下,“每个项”是一个元组,因此numpy将数组解释为一个3d数组,并将函数应用于元组中的每个项
因此,我可以假设传入阵列是以下阵列之一:
tuple\u converter
函数应用于数组中的每个元组
array_of_tuples1 = np.array([
[(1,2,3),(2,3,4),(5,6,7)],
[(7,2,3),(2,6,4),(5,6,6)],
[(8,2,3),(2,5,4),(7,6,7)],
])
array_of_tuples2 = np.array([
(1,2,3),(2,3,4),(5,6,7),
])
plain_tuple = (1,2,3)
# Convert each set of tuples
def tuple_converter(tup):
return tup[0]**2 + tup[1] + tup[2]
# Vectorizing applies the formula to each integer rather than each tuple
tuple_converter_vectorized = np.vectorize(tuple_converter)
print(tuple_converter_vectorized(array_of_tuples1))
print(tuple_converter_vectorized(array_of_tuples2))
print(tuple_converter_vectorized(plain_tuple))
元组1的数组的所需输出:
[[ 6 11 38]
[54 14 37]
[69 13 62]]
元组2的数组的所需输出:
[ 6 11 38]
普通元组的所需输出:
6
但是上面的代码会产生此错误(因为它试图将函数应用于整数而不是元组)
in-tuple\u转换器(tup)
10
11 def元组转换器(tup):
--->12返回tup[0]**2+tup[1]+tup[2]
13
14
索引器错误:标量变量的索引无效。
元组数组1和元组数组2实际上不是元组数组,而是三维和二维整数数组:
In [1]: array_of_tuples1 = np.array([
...: [(1,2,3),(2,3,4),(5,6,7)],
...: [(7,2,3),(2,6,4),(5,6,6)],
...: [(8,2,3),(2,5,4),(7,6,7)],
...: ])
In [2]: array_of_tuples1
Out[2]:
array([[[1, 2, 3],
[2, 3, 4],
[5, 6, 7]],
[[7, 2, 3],
[2, 6, 4],
[5, 6, 6]],
[[8, 2, 3],
[2, 5, 4],
[7, 6, 7]]])
因此,与其对函数进行矢量化,因为它将基本上通过数组的元素(整数)进行for循环,您应该(元组的轴)而不关心序列的类型:
In [6]: np.apply_along_axis(tuple_converter, 2, array_of_tuples1)
Out[6]:
array([[ 6, 11, 38],
[54, 14, 37],
[69, 13, 62]])
In [9]: np.apply_along_axis(tuple_converter, 1, array_of_tuples2)
Out[9]: array([ 6, 11, 38])
_tuples1的数组_和_tuples2的数组_实际上不是元组数组,而是三维和二维整数数组:
In [1]: array_of_tuples1 = np.array([
...: [(1,2,3),(2,3,4),(5,6,7)],
...: [(7,2,3),(2,6,4),(5,6,6)],
...: [(8,2,3),(2,5,4),(7,6,7)],
...: ])
In [2]: array_of_tuples1
Out[2]:
array([[[1, 2, 3],
[2, 3, 4],
[5, 6, 7]],
[[7, 2, 3],
[2, 6, 4],
[5, 6, 6]],
[[8, 2, 3],
[2, 5, 4],
[7, 6, 7]]])
因此,与其对函数进行矢量化,因为它将基本上通过数组的元素(整数)进行for循环,您应该(元组的轴)而不关心序列的类型:
In [6]: np.apply_along_axis(tuple_converter, 2, array_of_tuples1)
Out[6]:
array([[ 6, 11, 38],
[54, 14, 37],
[69, 13, 62]])
In [9]: np.apply_along_axis(tuple_converter, 1, array_of_tuples2)
Out[9]: array([ 6, 11, 38])
上面的另一个答案肯定是正确的,而且可能是您正在寻找的答案。但是我注意到你在你的问题中加入了“干净”这个词,所以我也想补充这个答案
如果我们可以假设所有元组都是3
元素元组(或者它们有一些固定数量的元素),那么有一个很好的小技巧可以让同一段代码在任何单个元组、1d元组数组或2d元组数组上工作,而对于1d/2d情况,没有If/else。我认为避免开关总是更干净的(尽管我认为这可能是有争议的)
根据需要(分别)为您的输入输出以下内容:
[[ 6 11 38]
[54 14 37]
[69 13 62]]
[ 6 11 38]
6
上面的另一个答案肯定是正确的,而且可能是您正在寻找的答案。但是我注意到你在你的问题中加入了“干净”这个词,所以我也想补充这个答案
如果我们可以假设所有元组都是3
元素元组(或者它们有一些固定数量的元素),那么有一个很好的小技巧可以让同一段代码在任何单个元组、1d元组数组或2d元组数组上工作,而对于1d/2d情况,没有If/else。我认为避免开关总是更干净的(尽管我认为这可能是有争议的)
根据需要(分别)为您的输入输出以下内容:
[[ 6 11 38]
[54 14 37]
[69 13 62]]
[ 6 11 38]
6
如果认真对待元组
位,可以定义结构化数据类型
In [535]: dt=np.dtype('int,int,int')
In [536]: x1 = np.array([
[(1,2,3),(2,3,4),(5,6,7)],
[(7,2,3),(2,6,4),(5,6,6)],
[(8,2,3),(2,5,4),(7,6,7)],
], dtype=dt)
In [537]: x1
Out[537]:
array([[(1, 2, 3), (2, 3, 4), (5, 6, 7)],
[(7, 2, 3), (2, 6, 4), (5, 6, 6)],
[(8, 2, 3), (2, 5, 4), (7, 6, 7)]],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
它适用于x1
In [539]: foo(x1)
Out[539]:
array([[ 6, 11, 38],
[54, 14, 37],
[69, 13, 62]])
它也适用于相同数据类型的1d数组
In [540]: x2=np.array([(1,2,3),(2,3,4),(5,6,7) ],dtype=dt)
In [541]: foo(x2)
Out[541]: array([ 6, 11, 38])
和匹配类型的0d数组:
In [542]: foo(np.array(plain_tuple,dtype=dt))
Out[542]: 6
但是foo(plain\u tuple)
不起作用,因为该函数是为使用命名字段而编写的,而不是索引字段
如果需要,可以修改该函数以将输入转换为正确的数据类型:
In [545]: def foo1(tup):
temp = np.asarray(tup, dtype=dt)
.....: return temp['f0']**2 + temp['f1'] + temp['f2']
In [548]: plain_tuple
Out[548]: (1, 2, 3)
In [549]: foo1(plain_tuple)
Out[549]: 6
In [554]: foo1([(1,2,3),(2,3,4),(5,6,7)]) # list of tuples
Out[554]: array([ 6, 11, 38])
如果认真对待元组
位,可以定义结构化数据类型
In [535]: dt=np.dtype('int,int,int')
In [536]: x1 = np.array([
[(1,2,3),(2,3,4),(5,6,7)],
[(7,2,3),(2,6,4),(5,6,6)],
[(8,2,3),(2,5,4),(7,6,7)],
], dtype=dt)
In [537]: x1
Out[537]:
array([[(1, 2, 3), (2, 3, 4), (5, 6, 7)],
[(7, 2, 3), (2, 6, 4), (5, 6, 6)],
[(8, 2, 3), (2, 5, 4), (7, 6, 7)]],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
它适用于x1
In [539]: foo(x1)
Out[539]:
array([[ 6, 11, 38],
[54, 14, 37],
[69, 13, 62]])
它也适用于相同数据类型的1d数组
In [540]: x2=np.array([(1,2,3),(2,3,4),(5,6,7) ],dtype=dt)
In [541]: foo(x2)
Out[541]: array([ 6, 11, 38])
和匹配类型的0d数组:
In [542]: foo(np.array(plain_tuple,dtype=dt))
Out[542]: 6
但是foo(plain\u tuple)
不起作用,因为该函数是为使用命名字段而编写的,而不是索引字段
如果需要,可以修改该函数以将输入转换为正确的数据类型:
In [545]: def foo1(tup):
temp = np.asarray(tup, dtype=dt)
.....: return temp['f0']**2 + temp['f1'] + temp['f2']
In [548]: plain_tuple
Out[548]: (1, 2, 3)
In [549]: foo1(plain_tuple)
Out[549]: 6
In [554]: foo1([(1,2,3),(2,3,4),(5,6,7)]) # list of tuples
Out[554]: array([ 6, 11, 38])
这里出现了一个小的“X-Y”问题-您能给出一个所需输出的示例吗?很好,我将把它添加到示例中,如果第一和第二种情况下所需输出的第一行是[6 11,38]
(其他行也会不同)?您希望函数映射每个元组,对吗?不是跨元组的吗?是的,我把它搞糟了,我正在努力修复它。很抱歉搞混了:/没问题,慢慢来,只是想澄清一下:)。这里出现了一个小的“X-Y”问题-你能给出一个你想要的输出的例子吗?很好,我会把它添加到示例中。如果第一和第二种情况下想要的输出的第一行是[6 11,38]
(其他行也会不同)?您希望函数映射每个元组,对吗?不是跨元组的吗?是的,我把它搞糟了,我正在努力修复它。抱歉搞混了:/没问题,慢慢来,我只是想说清楚:)。这太棒了。我甚至在文档中查看了这个函数,并认为它不是我所需要的。获得第二个意见总是很好;)这太棒了。我甚至在文档中查看了这个函数,并认为它不是我所需要的。获得第二个意见总是很好;)这是一个有趣的方法。我想也可以用同样的方式使用沿轴应用()。像你一样将输入包装在一个数组中,并沿最后一个轴应用(0表示普通元组输入)。哈哈!我会尽一切努力避免一个switch语句:p这是一个有趣的方法。可以使用沿轴应用()