2

我怎样才能编写一个使这项工作的包装类?

def foo(a, b):
    print a

data = np.empty(20, dtype=[('a', np.float32), ('b', np.float32)])

data = my_magic_ndarray_subclass(data)

foo(**data[0])

更多背景:

我有一对这样的函数,我想对其进行矢量化:

def start_the_work(some_arg):
    some_calculation = ...
    something_else = ...

    cost = some_calculation * something_else

    return cost, dict(
        some_calculation=some_calculation,
        some_other_calculation=some_other_calculation
    )

def finish_the_work(some_arg, some_calculation, some_other_calculation):
    ...

start_the_work用一堆不同的参数调用的意图,然后最低成本的项目就完成了。两个函数都使用了许多相同的计算,因此使用字典和 kwarg-splatting 来传递这些结果:

def run():
    best, best_cost, continuation = min(
        ((some_arg,) + start_the_work(some_arg)
         for some_arg in [1, 2, 3, 4]),
        key=lambda t: t[1]  # cost
    )
    return finish_the_work(best, **continuation)

我可以矢量化它们的一种方法如下:

def start_the_work(some_arg):
    some_calculation = ...
    something_else = ...

    cost = some_calculation * something_else

    continuation = np.empty(cost.shape, dtype=[
        ('some_calculation', np.float32),
        ('some_other_calculation', np.float32)
    ])
    continuation['some_calculation'] = some_calculation
    continuation['some_other_calculation'] = some_other_calculation

    return cost, continuation

但尽管看起来像一本字典,continuation但不能被夸夸其谈。

4

3 回答 3

2

它可能不是您想要的,但是将数组包装在 pandas DataFrame 中允许这样的事情:

import pandas as pd

def foo(a, b):
    print(a)

data = np.empty(20, dtype=[('a', np.float32), ('b', np.float32)])

data = pd.DataFrame(data).T

foo(**data[0])
# 0.0

请注意,数据框是转置的,因为 pandas 的主索引是列而不是行。

于 2016-04-15T04:45:19.000 回答
1

您是否认为因为可以通过名称访问结构化数组的字段,所以它们可能会作为字典的项目传递?

In [26]: x=np.ones((3,),dtype='i,f,i')

In [27]: x
Out[27]: 
array([(1, 1.0, 1), (1, 1.0, 1), (1, 1.0, 1)], 
      dtype=[('f0', '<i4'), ('f1', '<f4'), ('f2', '<i4')])

In [28]: x['f0']
Out[28]: array([1, 1, 1])

将其转换为字典有效:

In [29]: dd={'f0':x['f0'], 'f1':x['f1'], 'f2':x['f2']}

In [30]: def foo(**kwargs):
    ...:     print kwargs
    ...:     

In [31]: foo(**dd)
{'f0': array([1, 1, 1]), 'f1': array([ 1.,  1.,  1.], dtype=float32), 'f2': array([1, 1, 1])}

In [32]: foo(**x)  # the array itself won't work
...
TypeError: foo() argument after ** must be a mapping, not numpy.ndarray 

或使用字典理解:

In [34]: foo(**{name:x[name] for name in x.dtype.names})
{'f0': array([1, 1, 1]), 'f1': array([ 1.,  1.,  1.], dtype=float32), 'f2': array([1, 1, 1])}

**kwargs可能取决于具有.keys()方法的对象。数组没有。


结构化数组的元素是np.void

In [163]: a=np.array([(1,2),(3,4)],dtype='i,i')

In [164]: a[0]
Out[164]: (1, 2)

In [165]: type(a[0])
Out[165]: numpy.void

它有一个数据类型和名称:

In [166]: a[0].dtype.names
Out[166]: ('f0', 'f1')

In [167]: [{k:b[k] for k in b.dtype.names} for b in a]
Out[167]: [{'f0': 1, 'f1': 2}, {'f0': 3, 'f1': 4}]

与您的数组子类, aview有这个keys

class spArray(np.ndarray):
    def keys(self):
       return self.dtype.names

In [171]: asp=a.view(spArray)

In [172]: asp
Out[172]: 
spArray([(1, 2), (3, 4)], 
      dtype=[('f0', '<i4'), ('f1', '<i4')])

In [173]: asp.keys()
Out[173]: ('f0', 'f1')

构造此类的其他方式不起作用(即直接调用) - 这是子类化复杂性的一部分ndarray

def foo(**kwargs):
    print kwargs  

In [175]: foo(**asp)
{'f0': spArray([1, 3]), 'f1': spArray([2, 4])}

In [176]: foo(**asp[0])
 ...
TypeError: foo() argument after ** must be a mapping, not numpy.void 

In [177]: foo(**asp[[0]])
{'f0': spArray([1]), 'f1': spArray([2])}

喷溅数组,或从中提取的 1 元素数组有效,但元素,在这种情况下,np.void元素没有。它没有key方法。

我尝试np.void像你做数组一样进行子类化;它接受定义。但我找不到创建这样一个对象的方法。

于 2016-04-15T04:47:11.813 回答
0

这几乎有效:

class SplattableArray(np.ndarray):
    def keys(self):
        return self.dtype.names

data = np.empty(20, dtype=[('a', np.float32), ('b', np.float32)])
data_splat = data.view(SplattableArray)

def foo(a, b):
    return a*b

foo(**data_splat)  # works!
foo(**data_splat[0])  # doesn't work :(

如果我们愿意成为可怕的人,那么这行得通:

from forbiddenfruit import curse
import numpy as np

def keys(obj):
    return obj.dtype.names

curse(np.void, 'keys', keys)
curse(np.ndarray, 'keys', keys)

data = np.empty(10, dtype='i,i')
def foo(**kwargs):
    return kwargs

foo(**data[0])
foo(**data)
于 2016-04-16T02:50:54.790 回答