【问题标题】:flatten arrays in a list in python在python列表中展平数组
【发布时间】:2016-10-22 19:51:04
【问题描述】:

我有多个 numpy 掩码数组 arr0, arr1, ..., arrn。

我将它们放入列表arrs = [arr0, ..., arrn]。

我想展平这些阵列并在它们上面放置一个遮罩。我做了类似的事情:

for arr in arrs:
    arr = np.ravel(arr)
    arr[mask] = ma.masked

我不明白 Python 何时进行复制,何时它只是一个指针。这个for 循环不会展平arr0, ..., arrn,(而ravel 输出的是视图而不是副本)它只是展平了变量arr,尽管它确实改变了它们的掩码!

据我了解,arr 是列表arrs 中元素的视图,因此当我更改arr 的元素时,它会更改列表中相应数组的元素。但是当我为arr 分配一个新值时,它不会改变原始数组,即使分配应该是这个数组的一个视图。为什么?

举例编辑:

要展平的数组:

arr0 = masked_array(data=[[1,2],[3,4]], mask=False)
arr1 = masked_array(data=[[5,6],[7,8]], mask=False)
mask = [[False,True],[True,False]]

预期输出:

arr0 = masked_array(data=[[1,--],[--,4]], mask=[[False,True],[True,False]])
arr1 = masked_array(data=[[5,--],[--,8]], mask=[[False,True],[True,False]])

我想在循环中执行此操作,因为我有很多数组(或多或少 15 个),并且我想在代码中使用数组名称。有没有别的办法:

arr0 = np.ravel(arr0)
...
arrn = np.ravel(arrn)

【问题讨论】:

  • 您能否添加一个数字示例来说明您要实现的目标?
  • 问题出在列表迭代器上。你不能在循环中分配它。
  • arr = np.ravel(arr) 为arr 创建一个新的(扁平化)视图,并重新分配名称 arr 以指向该创建的视图。简单的分配只是reassigns names to point to something。正如您所指出的,ravel() 创建了一个视图,因此arr[mask] = ma.masked 也确实修改了原始视图。
  • 赋值和变异是不同的操作。变量始终只是引用。为新值分配名称总是只会更改引用所指的内容,而不是原始值。

标签: python arrays numpy view flatten


【解决方案1】:
In [1032]: arr0 = np.ma.masked_array(data=[[1,2],[3,4]], mask=False)    
In [1033]: arr1 = np.ma.masked_array(data=[[5,6],[7,8]], mask=False)

这是遍历列表、对每个元素应用一些操作并将结果收集到另一个列表中的基本方法:

In [1037]: ll=[arr0,arr1]    
In [1038]: ll1=[]
In [1047]: for a in ll:
    a1=a.flatten()   # makes a copy
    a1.mask=mask
    ll1.append(a1)

In [1049]: ll1
Out[1049]: 
[masked_array(data = [1 -- -- 4], mask = [False  True  True False],
        fill_value = 999999), 
        masked_array(data = [5 -- -- 8], mask = [False  True  True False],
        fill_value = 999999)]

通常可以写成列表理解

 [foo(a) for a in alist]

但这里的操作不是一个简洁的功能

如果我改用ravel,a1 是一个视图(不是副本),并且对其应用掩码也会更改a 的掩码 - 结果是更改了arr0 的掩码,但没有形状变化:

In [1051]: for a in ll:
   ......:     a1=a.ravel()
   ......:     a1.mask=mask

(您的 a=a.ravel() 也会发生同样的情况。a= 为 a 分配了一个新值,从而断开了指向迭代值的链接。对于任何 Python 迭代都是如此。最好在像a1 这样的迭代,所以你不要混淆自己。)

基本相同

In [1054]: for a in ll:
   ......:     a.mask=mask

我可以用同样的方式改变形状

In [1055]: for a in ll:
   ......:     a.shape=[-1]   # short hand for inplace ravel
   ......:     a.mask=mask   

In [1056]: arr0
Out[1056]: 
masked_array(data = [1 -- -- 4],
             mask = [False  True  True False],
       fill_value = 999999)

这是创建具有新形状和掩码的新数组并在列表理解中使用它的实用方法(arr0 没有变化)

[np.ma.masked_array(a,mask=mask).ravel() for a in [arr0,arr1]]

了解这些替代方案确实需要了解 Python 如何分配迭代变量,以及 numpy 如何制作副本和视图。

【讨论】:

    猜你喜欢
    • 2012-04-25
    • 2016-02-16
    • 2020-01-25
    • 2017-03-09
    • 2018-05-06
    • 2021-09-07
    • 2022-11-28
    • 1970-01-01
    相关资源
    最近更新 更多