numpy的fromfunction的参数

4si2a6ki  于 2023-10-19  发布在  其他
关注(0)|答案(7)|浏览(121)

我还没有理解numpy中的关键概念。
我想创建一个三维数组,并填充每个单元格与函数调用的结果-即。该函数将使用不同的索引被调用多次,并返回不同的值。

  • 注:自撰写此问题以来,文档已更新,更加清晰。*

我可以用零(或空)创建它,然后用for循环覆盖每个值,但直接从函数填充它似乎更干净。
fromfunction听起来很完美。Reading the documentation听起来像是每个单元格调用一次函数。
但当我真正尝试的时候...

from numpy import *

def sum_of_indices(x, y, z):
    # What type are X, Y and Z ? Expect int or duck-type equivalent.
    # Getting 3 individual arrays
    print "Value of X is:"
    print x

    print "Type of X is:", type(x)
    return x + y + z
    
a = fromfunction(sum_of_indices, (2, 2, 2))

我希望得到这样的东西:

Value of X is:
0
Type of X is: int
Value of X is:
1
Type of X is: int

重复4次。
我得到:

Value of X is:
[[[ 0.  0.]
  [ 0.  0.]]

 [[ 1.  1.]
  [ 1.  1.]]]
[[[ 0.  0.]
  [ 1.  1.]]

 [[ 0.  0.]
  [ 1.  1.]]]
[[[ 0.  1.]
  [ 0.  1.]]

 [[ 0.  1.]
  [ 0.  1.]]]
Type of X is: <type 'numpy.ndarray'>

该函数只被调用一次,并且似乎返回整个数组作为结果。
什么是正确的方法来填充数组的基础上多次调用一个函数的索引?

5us2dqdw

5us2dqdw1#

在这方面,文件是 * 非常 * 误导。就像你说的:numpy不执行f(0,0), f(0,1), f(1,0), f(1,1),而是执行

f([[0., 0.], [0., 1.]], [[1., 0.], [1., 1.]])

当你尝试使用像lambda i: l[i]这样的东西时,使用ndarrays而不是承诺的整数坐标是非常令人沮丧的,其中l是另一个数组或列表(尽管实际上,在numpy中可能有更好的方法来做到这一点)。
numpy vectorize函数解决了这个问题。在那里你有

m = fromfunction(f, shape)

尝试使用

g = vectorize(f)
m = fromfunction(g, shape)
vhmi4jdf

vhmi4jdf2#

很明显我没说清楚。我得到的响应是,fromfunc实际上可以像我的测试代码所演示的那样工作,我已经知道了,因为我的测试代码演示了它。
我所寻找的答案似乎分为两部分:
fromfunc文档具有误导性。它的工作原理是一次填充整个数组。

  • 注:自撰写此问题以来,文档已更新,更加清晰。*

特别是,documentation中的这一行是不正确的(或者至少是误导性的)。
例如,如果shape是(2,2),则参数依次是(0,0),(0,1),(1,0),(1,1)。
否。如果shape(即从上下文来看,fromfunction)的第二个参数是(2,2),这些参数将是(不是'依次',而是在唯一的调用中):

(array([[ 0.,  0.], [ 1.,  1.]]), array([[ 0.,  1.], [ 0.,  1.]]))
  • 文档已更新,目前更准确地阅读:*

该函数被调用时带有N个参数,其中N是形状的秩。每个参数表示阵列的坐标沿特定轴沿着变化。例如,如果shape是(2,2),则参数将是array([[0,0],[1,1]])和array([[0,1],[0,1]])
(My一个简单的例子,来自手册中的例子,可能会产生误导,因为+可以对数组和索引进行操作。这种模糊性是文档不清楚的另一个原因。我想最终使用一个不是基于数组的函数,而是基于单元格的函数-例如。每个值可以基于索引从URL或数据库中获取,或者甚至从用户输入。
回到这个问题--如何从每个元素调用一次的函数填充数组,答案似乎是:
你不能在一个功能性的风格。
你可以用命令式/迭代式的方式来做--也就是说。编写嵌套的for循环,自己管理索引长度。
你也可以把它作为迭代器来做,但是迭代器仍然需要跟踪它自己的索引。

bgtovc5b

bgtovc5b3#

我想你误解了fromfunction的作用。
numpysource code

def fromfunction(function, shape, **kwargs):
    dtype = kwargs.pop('dtype', float)
    args = indices(shape, dtype=dtype)
    return function(*args,**kwargs)

其中indices相当等价于meshgrid,其中每个变量都是np.arange(x)

>>> side = np.arange(2)
>>> side
array([0, 1])
>>> x,y,z = np.meshgrid(side,side,side)
>>> x
array([[[0, 0],
        [1, 1]],

       [[0, 0],
        [1, 1]]])
>>> x+y+z #Result of your code.
array([[[0, 1],
        [1, 2]],

       [[1, 2],
        [2, 3]]])
niknxzdl

niknxzdl4#

这给予你一个不正确的结果吗?a应该和预期的一样(我测试的时候也是这样),看起来是一个很好的方法来做你想做的事情。

>>> a
array([[[ 0.,  1.],    # 0+0+0, 0+0+1
        [ 1.,  2.]],   # 0+1+0, 0+1+1

       [[ 1.,  2.],    # 1+0+0, 1+0+1
        [ 2.,  3.]]])  # 1+1+0, 1+1+1

由于fromfunction在输入的数组索引上工作,因此您可以看到它只需要调用一次。文档中没有明确说明这一点,但你可以看到该函数在源代码(来自numeric.py)中的索引数组上被调用:

def fromfunction(function, shape, **kwargs):
    . . .
    args = indices(shape, dtype=dtype)
    return function(*args,**kwargs)

sum_of_indices在数组输入上被调用,其中每个数组保存该维度的索引值。

array([[[ 0.,  0.],
        [ 1.,  1.]],

       [[ 1.,  1.],
        [ 1.,  1.]]])

+

array([[[ 0.,  0.],
        [ 1.,  1.]],

       [[ 0.,  0.],
        [ 1.,  1.]]])

+
array([[[ 0.,  1.],
        [ 0.,  1.]],

       [[ 0.,  1.],
        [ 0.,  1.]]])

=

array([[[ 1.,  1.],
        [ 1.,  2.]],

       [[ 1.,  2.],
        [ 2.,  3.]]])
zynd9foi

zynd9foi5#

以下是我对你的问题的看法:

正如Chris Jones所提到的,解决方案的核心是使用np.vectorize

# Define your function just like you would
def sum_indices(x, y, z):
    return x + y + z

# Then transform it into a vectorized lambda function
f = sum_indices
fv = np.vectorize(f)

如果你现在执行np.fromfunction(fv, (3, 3, 3)),你会得到:

array([[[0., 1., 2.],
        [1., 2., 3.],
        [2., 3., 4.]],

       [[1., 2., 3.],
        [2., 3., 4.],
        [3., 4., 5.]],

       [[2., 3., 4.],
        [3., 4., 5.],
        [4., 5., 6.]]])

这是你想要的吗

xoefb8l8

xoefb8l86#

我认为大多数fromfunction的例子都使用方形数组有点令人困惑。
或许看看非正方形阵列会有帮助?

def f(x,y):
    print(f'x=\n{x}')
    print(f'y=\n{y}')
    return x+y

z = np.fromfunction(f,(4,3))
print(f'z=\n{z}')

结果:

x=
[[0 0 0]
 [1 1 1]
 [2 2 2]
 [3 3 3]]
y=
[[0 1 2]
 [0 1 2]
 [0 1 2]
 [0 1 2]]
z=
[[0 1 2]
 [1 2 3]
 [2 3 4]
 [3 4 5]]
hwazgwia

hwazgwia7#

如果将参数dtype设置为int,则可以获得所需的输出:
a = fromfunction(sum_of_indices, (2, 2, 2), dtype=int)
https://numpy.org/doc/stable/reference/generated/numpy.fromfunction.html

相关问题