Python 如何将具有不同形状数据数组的函数矢量化为参数?

Python 如何将具有不同形状数据数组的函数矢量化为参数?,python,python-3.x,numpy,vectorization,Python,Python 3.x,Numpy,Vectorization,我有以下功能: def reshape_to_array(in_dict, pattern): vec_func = np.frompyfunc(in_dict.get, 1, 1) return vec_func(pattern) func = np.frompyfunc(reshape_to_array,2,1) 输入: dump = np.array([[{'HH': 'a00', 'HV': 'b00', 'VH': 'c00', 'VV': 'd00'},

我有以下功能:

def reshape_to_array(in_dict, pattern):
    vec_func = np.frompyfunc(in_dict.get, 1, 1)
    return vec_func(pattern)
func = np.frompyfunc(reshape_to_array,2,1)
输入:

dump = np.array([[{'HH': 'a00', 'HV': 'b00', 'VH': 'c00', 'VV': 'd00'},
        {'HH': 'a01', 'HV': 'b01', 'VH': 'c01', 'VV': 'd01'},
        {'HH': 'a02', 'HV': 'b02', 'VH': 'c02', 'VV': 'd02'},
        {'HH': 'a03', 'HV': 'b03', 'VH': 'c03', 'VV': 'd03'}],
       [{'HH': 'a10', 'HV': 'b10', 'VH': 'c10', 'VV': 'd10'},
        {'HH': 'a11', 'HV': 'b11', 'VH': 'c11', 'VV': 'd11'},
        {'HH': 'a02', 'HV': 'b02', 'VH': 'c02', 'VV': 'd02'},
        {'HH': 'a13', 'HV': 'b13', 'VH': 'c13', 'VV': 'd13'}],
       [{'HH': 'a20', 'HV': 'b20', 'VH': 'c20', 'VV': 'd20'},
        {'HH': 'a21', 'HV': 'b21', 'VH': 'c21', 'VV': 'd21'},
        {'HH': 'a22', 'HV': 'b22', 'VH': 'c22', 'VV': 'd22'},
        {'HH': 'a23', 'HV': 'b23', 'VH': 'c23', 'VV': 'd23'}],
       [{'HH': 'a30', 'HV': 'b30', 'VH': 'c30', 'VV': 'd30'},
        {'HH': 'a31', 'HV': 'b31', 'VH': 'c31', 'VV': 'd31'},
        {'HH': 'a32', 'HV': 'b32', 'VH': 'c32', 'VV': 'd32'},
        {'HH': 'a33', 'HV': 'b33', 'VH': 'c33', 'VV': 'd33'}]])

pattern = np.array([['HH', 'HV'], ['VH', 'VV']])
当我执行:

x = func(dump, pattern)
它抛出ryuntime错误:

ValueError: operands could not be broadcast together with shapes (4,4) (2,2)
但是,如果我以以下方式修改
将_重塑为_数组
函数:

# pattern is global
pattern = np.array([['HH', 'HV'], ['VH', 'VV']])
def reshape_to_array(in_dict):
    vec_func = np.frompyfunc(in_dict.get, 1, 1)
    return vec_func(pattern)
func = np.frompyfunc(reshape_to_array,1,1)
并执行
func(dump)
它成功执行并返回预期(正确)输出。即:

x = np.array([[array([['a00', 'b00'],
       ['c00', 'd00']]),
        array([['a01', 'b01'],
       ['c01', 'd01']]),
        array([['a02', 'b02'],
       ['c02', 'd02']]),
        array([['a03', 'b03'],
       ['c03', 'd03']])],
       [array([['a10', 'b10'],
       ['c10', 'd10']]),
        array([['a11', 'b11'],
       ['c11', 'd11']]),
        array([['a02', 'b02'],
       ['c02', 'd02']]),
        array([['a13', 'b13'],
       ['c13', 'd13']])],
       [array([['a20', 'b20'],
       ['c20', 'd20']]),
        array([['a21', 'b21'],
       ['c21', 'd21']]),
        array([['a22', 'b22'],
       ['c22', 'd22']]),
        array([['a23', 'b23'],
       ['c23', 'd23']])],
       [array([['a30', 'b30'],
       ['c30', 'd30']]),
        array([['a31', 'b31'],
       ['c31', 'd31']]),
        array([['a32', 'b32'],
       ['c32', 'd32']]),
        array([['a33', 'b33'],
       ['c33', 'd33']])]])
我的问题是:

  • 为什么函数在第一种情况下不工作,但在第二种情况下工作良好
  • 如何克服这个问题

  • 您的第一个
    func
    接受两个相互广播的输入,元素元组被传递到
    restrape\u to\u数组

    转储
    为(4,4),
    模式
    为(2,2)。错误是说它可以将2配对-如果你理解广播,这应该是显而易见的

    如果您将
    dump
    减少到(2,2)(或(2,1)或(1,2)),它应该可以工作。一个
    模式
    也是如此,即(1,4)或(4,1)


    在第二种情况下,pyfunc的外部
    将(4,4)
    dump
    元素传递给
    重塑数组。并对
    (4,4)
    模式进行评估

    我怀疑
    x=func(dump[:,:,np.newaxis,np.newaxis],pattern)
    会起作用,生成相同的值,但是在(4,4,2,2)数组中。通过不同的
    np.newaxis
    安排,我们可以生产(4,2,4,2)等

    广播口述与模式 使用(4,4)
    转储
    ,我可以使用(1,4)
    模式
    (或(4,1)):

    如果我将
    newaxis
    添加到
    dump
    中,我可以得到一个(4,4,2,2)数组:

    除了没有(4,4)(2,2)嵌套之外,它们与
    x
    相同

    如果我复制-n-粘贴您的
    x
    ,它会生成一个(4,4,2,2)'U3'数组(它不会保留嵌套),并比较:

    In [309]: np.all(xx == Out[302].astype('U3'))
    Out[309]: True
    
    包裹图案 您可以在函数定义中包装上一个版本:

    def foo(pattern):
        def reshape_to_array(in_dict):
            vec_func = np.frompyfunc(in_dict.get, 1, 1)
            return vec_func(pattern)
        func = np.frompyfunc(reshape_to_array,1,1)
        return func
    
    将用作:

    In [313]: foo(pattern)
    Out[313]: <ufunc '? (vectorized)'>
    In [314]: foo(pattern)(dump)
    # your x
    
    使用复杂类型进行矢量化
    我明白你的意思。我实际需要的是第二个函数的结果,但不需要硬编码模式。另外,我需要这种泛化,因为模式的形状可能并不总是2x2。
    np.vectorize
    使用
    np.frompyfunc
    ,并允许您从“向量化”中排除某些参数,我认为它通过覆盖函数传递这些参数。您的意思是
    func=np.vectorize(重塑到数组,排除=[“模式”])
    ?我刚才尝试了这个,抛出了相同的运行时错误。最后一个是最简单的解决方案。我没有想到在函数调用本身中它应该被指定为pattern=pattern。这似乎是合乎逻辑的,因为它在矢量化中被排除,python函数参数没有排序。谢谢。我尝试替换
    vec\u func=np.frompyfunc(in_dict.get,1,1)
    to
    vec_func=np.vectorize(in_dict.get)
    这样就可以返回正确的
    dtype
    而不是
    object
    。但这不起作用,并引发运行时错误,声明
    TypeError:只有length-1数组可以转换为Python标量
    。这很奇怪,因为
    vectorize
    基本上是
    frompyfunc
    的包装器。
    In [309]: np.all(xx == Out[302].astype('U3'))
    Out[309]: True
    
    def foo(pattern):
        def reshape_to_array(in_dict):
            vec_func = np.frompyfunc(in_dict.get, 1, 1)
            return vec_func(pattern)
        func = np.frompyfunc(reshape_to_array,1,1)
        return func
    
    In [313]: foo(pattern)
    Out[313]: <ufunc '? (vectorized)'>
    In [314]: foo(pattern)(dump)
    # your x
    
    In [334]: def reshape_to_array(in_dict, pattern=None):
         ...:     vec_func = np.frompyfunc(in_dict.get, 1, 1)
         ...:     return vec_func(pattern)
    
    In [335]: f = np.vectorize(reshape_to_array, excluded=['pattern'], otypes=['O'])
    In [336]: f(dump, pattern=pattern)
    
    In [380]: def reshape_to_array1(in_dict, pattern=None):
         ...:     vec_func = np.vectorize(in_dict.get, otypes=[complex])
         ...:     return vec_func(pattern)
         ...: 
         ...: 
    In [381]: f = np.vectorize(reshape_to_array1, excluded=['pattern'], otypes=['O
         ...: '])
    In [382]: dd = np.array([{'HH': 1+j, 'HV': 1j, 'VH':2j, 'VV': 1+2j}])
    In [383]: f(dd, pattern=pattern)
    Out[383]: 
    array([array([[3.+0.j, 0.+1.j],
           [0.+2.j, 1.+2.j]])], dtype=object)