【问题标题】:What is the difference between flatten and ravel functions in numpy?numpy中的flatten和ravel函数有什么区别?
【发布时间】:2015-05-09 22:16:19
【问题描述】:
import numpy as np
y = np.array(((1,2,3),(4,5,6),(7,8,9)))
OUTPUT:
print(y.flatten())
[1   2   3   4   5   6   7   8   9]
print(y.ravel())
[1   2   3   4   5   6   7   8   9]

两个函数都返回相同的列表。 那么两个不同的功能执行相同的工作需要什么。

【问题讨论】:

  • Ravel 通常会在现有数组中返回一个视图(有时它会返回一个副本)。 Flatten 返回一个新数组。
  • Here 是细微差别的实际演示。
  • 那么有人可以举一个例子,什么时候最好展平一个数组,什么时候拆散它?
  • 谢谢你的提问,我也有同样的问题。

标签: python numpy multidimensional-array flatten numpy-ndarray


【解决方案1】:

目前的 API 是:

  • flatten 总是返回一个副本。
  • ravel 尽可能返回原始数组的视图。这在打印输出中不可见,但是如果您修改 ravel 返回的数组,它可能会修改原始数组中的条目。如果您修改从 flatten 返回的数组中的条目,这将永远不会发生。 ravel 通常会更快,因为没有复制内存,但您必须更加小心地修改它返回的数组。
  • 只要数组的步幅允许reshape((-1,)) 获得视图,即使这意味着您并不总是获得连续的数组。

【讨论】:

  • 知道为什么 NumPy 开发人员不坚持使用某些参数 copy=[True,False] 的功能吗?
  • Backcompat 保证有时会导致发生这种奇怪的事情。例如:numpy 开发人员最近(在 1.10 中)添加了一个先前隐含的保证,即 ravel 将返回一个连续的数组(在编写 C 扩展时非常重要的一个属性),所以现在 API 是a.flatten() 以确保得到一个副本, a.ravel() 避免大多数副本,但仍保证返回的数组是连续的,a.reshape((-1,)) 可以在数组的步幅允许时真正获得视图,即使这意味着您并不总是得到一个连续的数组。
  • @Hossein IanH 解释说:ravel保证一个连续的数组,因此不能保证它返回一个视图; reshape 总是返回一个视图,因此不能保证它返回一个连续的数组。
  • @Hossein 那将是一个全新的问题。简而言之,读取和写入连续的内存空间要快得多。 SO (nice example here) 上有几个问题和答案,如果您有任何其他问题,请随时打开一个新问题。
  • 为什么叫ravel?这个名字背后的想法是什么?
【解决方案2】:

正如here 所解释的,一个关键的区别在于:

  • flatten 是 ndarray 对象的方法,因此只能为真正的 numpy 数组调用。

  • ravel 是库级函数,因此可以在任何可以成功解析的对象上调用。

例如,ravel 将适用于 ndarray 列表,而 flatten 不适用于该类型的对象。

@IanH 在他的回答中还指出了与内存处理的重要区别。

【讨论】:

  • 感谢有关在 ndarray 列表上工作的 ravel() 的信息
  • 不仅是数组列表,还有列表列表 :)
【解决方案3】:

这是函数的正确命名空间:

两个函数都返回指向新内存结构的扁平一维数组。

import numpy
a = numpy.array([[1,2],[3,4]])

r = numpy.ravel(a)
f = numpy.ndarray.flatten(a)  

print(id(a))
print(id(r))
print(id(f))

print(r)
print(f)

print("\nbase r:", r.base)
print("\nbase f:", f.base)

---returns---
140541099429760
140541099471056
140541099473216

[1 2 3 4]
[1 2 3 4]

base r: [[1 2]
 [3 4]]

base f: None

在上面的例子中:

  • 结果的内存位置不同,
  • 结果看起来一样
  • flatten 会返回一个副本
  • ravel 会返回一个视图。

我们如何检查某个东西是否是副本? 使用ndarray.base 属性。如果是视图,则基数将是原始数组;如果是副本,则基数为None


检查a2 是否是a1 的副本

import numpy
a1 = numpy.array([[1,2],[3,4]])
a2 = a1.copy()
id(a2.base), id(a1.base)

输出:

(140735713795296, 140735713795296)

【讨论】:

  • id(a1.base) 应与id(a2.base) 相同
猜你喜欢
  • 2015-05-04
  • 2016-11-16
  • 2018-08-24
  • 2019-12-05
  • 2013-01-03
相关资源
最近更新 更多