【问题标题】:Using scipy.io.savemat to Save Nested Lists使用 scipy.io.savemat 保存嵌套列表
【发布时间】:2016-12-21 23:26:14
【问题描述】:

这与我的最后一个问题有关,可以在here 找到。我正在处理的列表类似于我在该链接中描述为 markerList 的列表 - 所以是一个具有三个级别的列表。我需要将此信息保存为 .mat 文件,但我无法将其保存为正确的类型。使用 scipy.io.savemat 时,它将列表保存为 200x40x2 的单个,当它应该是一组 200 个单元格时,每个单元格包含一个 40x2 单元格。

我用来保存的代码是:

matdict = dict(markers = (markerList), sorted = (finalStack))
scipy.io.savemat('C:\pathname\\sortedMarkers.mat', matdict)

让我感到困惑的是,它以正确的格式保存 markerList(1x200 单元格,每个单元格大小不一),但不是 finalStack(保存为 200 x 40 x 2 单个)。最重要的是,在我弄清楚这段代码的其余部分之前,它会正确保存 finalStack - 这让我认为当它保存的数据大小不统一时,它可能会保存为一个单元格。 (finalStack 的大小是一致的;markerList 不是。)

有没有办法将这种复杂的数据结构保存为 .mat 文件?

【问题讨论】:

  • 我要问一下,只是为了确认这不是XY Problem 的情况,你会在Matlab 中使用它吗?还是您只是使用scipy.io.savemat 作为保存python 工作区的通用库?因为如果是后者,还有更好的选择。
  • 但是使用savemat 在您期望的 (20,) 数组 (40,2) 数组的位置保存 (200,40,2) 数组不是问题。如果我的诊断是正确的,那么 numpy 如何将数组列表转换为数组是一个问题。
  • Tasos- 这不是 XY 问题。基本上与我一起工作的每个人都使用 Matlab,并且单元格数组与我所知道的嵌套列表最相似。此外,一旦以适当的格式保存数据,我已经编写了脚本来批处理我的数据(不是不能重做的东西,但仍然是动力)。在保存大量这样的嵌套数据时,任何其他格式都显得非常庞大和笨拙。

标签: python python-2.7 scipy


【解决方案1】:

按照savemat documentation,转换成一个“对象”的numpy数组:

from scipy.io import savemat
import numpy

a = numpy.array([[1,2,3],[1,2,3]])
b = numpy.array([[2,3,4],[2,3,4]])
c = numpy.array([[3,4,5],[3,4,5]])
L = [a,b,c]

FrameStack = numpy.empty((len(L),), dtype=numpy.object)
for i in range(len(L)):
    FrameStack[i] = L[i]

savemat("myfile.mat", {"FrameStack":FrameStack})

八度:

>> load myfile.mat 

>> whos FrameStack
Variables in the current scope:

   Attr Name            Size                     Bytes  Class
   ==== ====            ====                     =====  ===== 
        FrameStack      1x3                        144  cell

Total is 3 elements using 144 bytes

>> whos FrameStack{1}
Variables in the current scope:

   Attr Name               Size                     Bytes  Class
   ==== ====               ====                     =====  ===== 
        FrameStack{1}      2x3                         48  int64

Total is 6 elements using 48 bytes

【讨论】:

  • 但是当A,B,C 的形状都一样时会发生什么?
  • 我明白你在这里得到了什么,但我的列表的内容是相关的和依赖的。也就是说,我不能只将 finalStack[0][1][0] 分解为单独的元素;在那一点上是没有意义的。无论如何,我明白你在说什么,我也许可以从这里弄清楚......
  • 我意识到我需要创建一个 Python 对象,其中 finalStack[0][0] 在 Matlab 中是 {1}(1),但我无法弄清楚,因此提出了问题。但是,将 finalStack 附加到列表(b.append(finalStack[i]) 超出范围,其中b = [ ])并不能解决问题 - 它们仍然保存为单个。 (finalStack[i] 是所有元素 i 的 40x2 np.array。)仍在努力,只是还没有运气。
  • 我同意。我认为现在最快完成这项工作的最简单方法是在 mat 文件发布时搞砸它,而不是试图弄乱 Python 解释。试图最小化 Matlab 端的工作,但这就是生活。感谢您的帮助!
  • @godfreap 抱歉,我只是重新运行您的示例,我明白您对相同形状的意思是什么导致连接数组。解决方案是改用 numpy.object 数组;这在 savemat 文档中有所说明。我会更新我的答案给你看一个例子。
【解决方案2】:

不再查看您之前的问题,我怀疑问题出在numpy.array 从子列表或数组列表中创建数组。

您注意到markerList 已按预期保存,并且单元格大小不同。

试试

np.array(markerList)

并查看它的形状和数据类型。我猜它会是 1d (200,) 和 object dtype。

np.array(finalStack)

另一方面,可能是它保存的 3d 数组。

savemat 设置为保存 numpy 数组,而不是 python 字典和列表 - 之后,所有内容都与 MATLAB 对话,其中所有内容都曾经是 2d 矩阵。 MATLAB 单元对此进行了概括;它们更像是 dtype 对象的 2d numpy 数组。

从大小一致的元素创建对象数组的问题经常出现。通常的解决方案是创建所需大小(例如 (200,))和对象类型的 empty 数组,并将子数组加载到其中。

https://stackoverflow.com/a/38776674/901925

=============

我会演示。制作 3 个数组,2 个大小相同,第三个不同:

In [59]: from scipy import io

In [60]: A=np.ones((40,2))    
In [61]: B=np.ones((40,2))
In [62]: C=np.ones((30,2))

保存两个列表,一个只有两个数组,另一个包含所有三个:

In [63]: io.savemat('test.mat', {'AB':[A,B],'ABC':[A,B,C]})

加载它;我可以在octave 中这样做:

In [65]: D=io.loadmat('test.mat')

In [66]: D.keys()
Out[66]: dict_keys(['ABC', '__header__', 'AB', '__globals__', '__version__'])

ABC 是一个包含 3 个元素的二维数组

In [68]: D['ABC'].shape
Out[68]: (1, 3)
In [71]: D['ABC'][0,0].shape
Out[71]: (40, 2)

AB 已被转换为 3d 数组:

In [69]: D['AB'].shape
Out[69]: (2, 40, 2)
In [70]: np.array([A,B]).shape
Out[70]: (2, 40, 2)

如果我改为创建一个 1d 对象数组来保存 A 和 B,它会被保留:

In [72]: AB=np.empty((2,),object)
In [73]: AB[...]=[A,B]
In [74]: AB.shape
Out[74]: (2,)

In [75]: io.savemat('test.mat', {'AB':AB,'ABC':[A,B,C]})
In [76]: D=io.loadmat('test.mat')

In [77]: D['AB'].shape
Out[77]: (1, 2)
In [78]: D['AB'][0,0].shape
Out[78]: (40, 2)

一个不错的选择是将数组保存为字典项

io.savemat('test.mat',{'A':A, 'B':B, 'C':C})

考虑到将 MATLAB 结构转换为 numpy 结构并返回的困难,最好让事情保持平坦和简单,而不是创建对双方都有用的复合对象。

================

我安装了Octave。正在加载这个test.mat

io.savemat('test.mat', {'AB':AB,'ABs':[A,B]})

给予

>> whos
Variables in the current scope:

   Attr Name        Size                     Bytes  Class
   ==== ====        ====                     =====  =====
        AB          1x2                       1280  cell
        ABs         2x40x2                    1280  double

对象 dtype 数组保存为 matlab 单元格;其他数组作为 matlab 矩阵。 (我必须回顾之前的答案才能回忆起 matlab 结构的等价物)。

【讨论】:

    猜你喜欢
    • 2021-04-07
    • 2011-01-09
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    相关资源
    最近更新 更多