【问题标题】:Python equivalent code to MATLABs vec2mat与 MATLAB vec2mat 等效的 Python 代码
【发布时间】:2013-09-02 22:28:56
【问题描述】:

我有一段代码正在从 MATLAB 转换为 python。它还没有以非常pythonic的方式编写,但我会在稍后阶段对其进行调整。

MATLAB 脚本具有来自通信系统工具箱的函数 vec2mat。 (请参阅http://www.mathworks.co.uk/help/comm/ref/vec2mat.html)这通过指定您希望转换的向量和您希望拥有的列数将向量更改为矩阵来工作。 mat = vec2mat(vec,matcol).

我通常只使用numpy.reshape。但是,如果向量中没有足够的值来完全填充最后一行,vec2mat 会在最后一行添加零。

我需要的填充将根据我输入的 csv 文件而有所不同。

    atbmat = vec2mat(atbvec,nb);

在本例中,nb 为 5,atbvec 的长度为 4806。因此,最后一行添加了四个零。

如何在 python 中添加额外的零来创建二维数组?我会让长度为 4806 的一维数组 atbvecnb 等于五(我想要 nb 列)。

感谢您的任何建议,我希望这是有道理的。

编辑

     dim=len(atbvec)/int(nb)
     atbvec=np.array(atbvec)
     atbvec=np.copy(atbvec)
     atb_mat=atbvec.resize((dim,nb)

这是返回None

【问题讨论】:

    标签: python arrays matlab numpy reshape


    【解决方案1】:

    您可以使用numpy.ndarray 对象的resize() 方法:

    import numpy as np
    
    a = np.array([1,2,3])
    a.resize(2,3)
    print a
    #array([[1, 2, 3],
    #       [0, 0, 0]])
    

    编辑:

    请注意,ain-place 的扩展,这意味着原始数组现在具有对额外连续内存块的引用。

    在您的情况下,基于 cmets,您可以预先创建一个副本:

    atb_mat = atbvec.copy()
    atb_mat.resize(dim, nb)
    

    或者,最好,使用numpy.resize获得一个没有引用的全新数组:

    atb_mat = numpy.resize(atbvec, (dim, nb))
    

    不过,在这种情况下,数组会填充来自 atbvec 的先前值,例如:

    a = np.array([1,2,3])
    b = np.resize(a, (3, 4))
    #array([[1, 2, 3, 1],
    #       [2, 3, 1, 2],
    #       [3, 1, 2, 3]])
    

    看到内存块被复制,直到它填满新的连续大小。

    【讨论】:

    • 非常感谢您的快速回复。听起来它应该工作。但是,我得到输出 'None' (dim=len(atbvec)/int(nb) atbvec=np.array(atbvec) atb_mat=atbvec.resize((dim,nb)) print atb_mat return atb_mat)
    • 除了resize 只是将零添加到连续的内存块。考虑a = np.array([[1],[2],[3]]).copy(); a.resize(3, 2)
    • @SaulloCastro 非常感谢,解决了我的问题!非常明确的答案
    • 我在我的答案中添加了一个编辑。问题是扩展不是形状感知的,因此只是将数据填充到内存中,而不是逻辑数组中。
    • 哦,我失败了!似乎mat2vec 确实做了你回答的事情(尽管是在行主要数据上)。我宁愿离开这个问题而不是 Mathworks 页面。我会留下我的答案,以防万一有用!
    【解决方案2】:

    压倒一切的编辑:似乎我误解了这个问题,并完全解决了另一个问题。下面的解决方案是,如果您需要将数组扩展或缩小到任意大小,必要时用零填充。

    我不知道有哪个函数可以按您的要求执行(尽管我一直在学习!)。我能想到的最简单的方法可能是使用numpy.pad。只要新形状比旧形状大,以下函数就可以满足您的需求:

    def vec2mat(a, new_shape):
    
        padding = (new_shape - numpy.vstack((new_shape, a.shape))).T.tolist()
    
        return numpy.pad(a, padding, mode='constant')
    

    如果您需要处理比原始数组更小和更大的大小,则应执行以下操作:

    def vec2mat(a, shape):
    
        padding = (shape - numpy.vstack((shape, a.shape))).T
    
        # Split into positive and negative padding
        neg_padding = padding.copy()
        neg_padding[neg_padding > 0] = 0
        padding[padding < 0] = 0
    
        # Turn the zero neg_paddings into None:
        slice_marks = [axis if axis[1] != 0 else (None,) for axis in neg_padding]
    
        # Make the slicer
        slicer = [slice(*each_mark) for each_mark in slice_marks]
    
        return numpy.pad(a[slicer], padding.tolist(), mode='constant')
    

    请注意,以上两个函数都应该对任意维度的数组进行操作。

    编辑:resize 作为解决方案的问题在于它仅在内存中扩展数组,然后有效地将新内存块重塑为您请求的大小。这样做的效果是,如果您尝试沿除最短轴以外的任何轴进行扩展,您将遇到问题。考虑沿第一个轴扩展:

    a = np.array([1,2,3]).copy()
    a.resize(2, 3)
    # array([[1, 2, 3],
    #        [0, 0, 0]])
    

    按预期工作。但是,现在考虑沿最后一个轴扩展:

    a = np.array([[1],[2],[3]]).copy()
    a.resize(3, 2)
    # array([[1, 2],
    #        [3, 0],
    #        [0, 0]])
    

    我认为这根本不是您想要的,但如果我错了,请纠正我。我的理解是您需要一个数组,其中第一列为[[1],[2],[3]],第二列全为零。

    【讨论】:

    • 如果OP想要扩展第二列,只需要使用行连续的内存布局,如果a是用a = np.array([1,2,3], order='F')创建的,就可以实现这一点
    • 对不起,我只是在这里测试了它,它不起作用......奇怪......它改变了内存布局,检查.flags
    • @SaulloCastro 我认为我的解决方案无论如何都不能满足要求。它解决了一个不同的问题——特别是沿所有维度填充或缩小数组。
    • @AshleighClayton 确实如此!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2017-12-25
    • 1970-01-01
    相关资源
    最近更新 更多