【问题标题】:Why does this array-reshaping routine work outside of a function but not inside of a function?为什么这个数组重塑例程在函数外部起作用,但在函数内部不起作用?
【发布时间】:2017-03-30 02:53:21
【问题描述】:

我正在尝试将列表转换为具有指定列数的 numpy 数组。我可以让代码在函数之外工作,如下所示:

import numpy as np

ls = np.linspace(1,100,100) # Data Sample
ls = np.array(ls) # list --> array

# resize | outside function
ls.resize(ls.shape[0]//2,2)
print(ls)

>> [[   1.    2.]
    [   3.    4.]
           .
           .
           .
    [  97.   98.]
    [  99.  100.]]

尝试将例程放入函数中时,我不明白我的错误。我的尝试如下:

# resize | inside function
def shapeshift(mylist, num_col):
    num_col = int(num_col)
    return mylist.resize(mylist.shape[0]//num_col,num_col)

ls = shapeshift(ls,2)
print(ls)

>> None

我想以这种方式定义原始函数,因为我想要另一个函数,由相同的输入和第三个输入组成,在提取值时循环遍历行,为每个遍历行调用这个原始函数。

【问题讨论】:

  • 我怀疑resize 在原地工作并返回None。尝试稍后返回 mylist 本身。
  • 在一行之后返回mylist 对函数输出没有影响。如果resize 就地工作,是否有更有效、更方便的方法可以在没有 for 循环的情况下实现这一目标?最后,我想定义另一个具有相同输入和第三个输入的函数,这样我就可以调用上面的函数并遍历每一行。
  • 显然函数形式(即np.resize(a, new_shp),而不是方法形式a.resize(new_shp))不能就地工作并创建一个新数组。所以你可以尝试使用它。
  • 我试过这个方法,但它只返回第一个 new_shp 元素。如果new_shp=2,则返回[1,2]。对于这个示例,我想我可以将函数参数设置为从 2 到 100 的偶数列表,但我仍然希望有一种更有效的方法来做到这一点。
  • 你可以为new_shp使用一个元组;喜欢np.reshape(a, (m, n))。在你的例子中m=50, n=2.

标签: arrays python-3.x numpy reshape array-broadcasting


【解决方案1】:
In [402]: ls = np.linspace(1,100,10)
In [403]: ls
Out[403]: array([   1.,   12.,   23.,   34.,   45.,   56.,   67.,   78.,   89.,  100.])
In [404]: ls.shape
Out[404]: (10,)

无需再次包裹array;它已经是一个:

In [405]: np.array(ls)
Out[405]: array([   1.,   12.,   23.,   34.,   45.,   56.,   67.,   78.,   89.,  100.])

resize 就地运行。它什么也不返回(或无)

In [406]: ls.resize(ls.shape[0]//2,2)
In [407]: ls
Out[407]: 
array([[   1.,   12.],
       [  23.,   34.],
       [  45.,   56.],
       [  67.,   78.],
       [  89.,  100.]])
In [408]: ls.shape
Out[408]: (5, 2)

有了这个resize,你并没有改变元素的数量,所以reshape也可以工作。

In [409]: ls = np.linspace(1,100,10)
In [410]: ls.reshape(-1,2)
Out[410]: 
array([[   1.,   12.],
       [  23.,   34.],
       [  45.,   56.],
       [  67.,   78.],
       [  89.,  100.]])

reshape 在方法或函数形式中返回一个值,而 ls 保持不变。 -1 是一个方便的简写,避免了 // 部门。

这是 reshape 的就地版本:

In [415]: ls.shape=(-1,2)

reshape 需要相同的元素总数。 resize 允许您更改元素的数量,如果需要,可以截断或重复值。我们使用reshape 比resize 更频繁。 repeat 和 tile 也比 resize 更常见。

【讨论】:

  • 这个例子是一个很好的教程。谢谢。
【解决方案2】:

.resize 方法在原地工作并返回None。如果有其他名称引用同一个数组,它也完全拒绝工作。你可以使用函数形式,它创建一个新数组并且没有那么任性:

def shapeshift(mylist, num_col):
    num_col = int(num_col)
    return np.resize(mylist, (mylist.size//num_col,num_col))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-16
    • 2021-09-16
    • 2016-04-01
    • 2022-01-16
    相关资源
    最近更新 更多