【问题标题】:numpy array creating with a sequence用序列创建的numpy数组
【发布时间】:2012-05-25 11:23:05
【问题描述】:

我正在从 MATLAB 过渡到 scipy(+numpy)+matplotlib。在实施某些事情时,我一直遇到问题。 我想在三个不同的部分创建一个简单的向量数组。在 MATLAB 中,我会执行以下操作:

vector=[0.2,1:60,60.8];

这会产生一个包含 62 个位置的一维数组。我正在尝试使用 scipy 来实现这一点。我现在最接近的是:

a=[[0.2],linspace(1,60,60),[60.8]]

但是,这会创建一个列表,而不是数组,因此我无法将其重塑为向量数组。但是,当我这样做时,我得到一个错误

a=array([[0.2],linspace(1,60,60),[60.8]])
ValueError: setting an array element with a sequence.

我认为我的主要障碍是我不知道如何在 MATLAB 中翻译这个简单的操作:

a=[1:2:20];

到 numpy.我知道如何访问数组中的位置,尽管在创建序列时不知道。 任何帮助将不胜感激, 谢谢!

【问题讨论】:

    标签: python arrays numpy scipy sequence


    【解决方案1】:

    你可以试试这样的:

    a = np.hstack(([0.2],np.linspace(1,60,60),[60.8]))
    

    【讨论】:

    • 真的!这也有效,谢谢 JoshAdel。此外,每当我想做 a=[1:2:20] 之类的事情时,linspace 是唯一的选择吗?这意味着我不知道向量的最终大小,只知道步骤和起点/终点。 [之二]
    • 多亏了 mgilson,我自己才发现它。答案是范围(开始、停止、步进)。太棒了!
    • @vint-i-vuit 请注意,python 内置范围函数仅适用于整数值。 Numpy 提供了 arange 它将做同样的事情(如果你想要它也可以使用浮点数)返回一个数组,但文档指出 linspace 在大多数情况下是一个更好的选择,因为(由于四舍五入),结果来自arange 可能不是你所期望的。
    • @mgilson 感谢您的洞察力。但是,我通常比 linspace 更需要 range/arange 的功能(我在 MATLAB 中很少使用 linspace)。因为我倾向于实现知道步长而不是最终向量大小的数组。我会考虑到这一点!
    【解决方案2】:

    NumPy 实现了 MATLAB 的数组创建函数,vector,使用 两个 函数而不是一个 - 每个都隐含指定一个特定的轴,concatenation em> 应该发生。这些功能是:

    • r_(逐行连接)和

    • c_(按列)


    因此,对于您的示例,NumPy 等价物是:

    >>> import numpy as NP
    
    >>> v = NP.r_[.2, 1:10, 60.8]
    
    >>> print(v)
         [  0.2   1.    2.    3.    4.    5.    6.    7.    8.    9.   60.8]
    

    按列对应的是:

    >>> NP.c_[.2, 1:10, 60.8]
    

    slice 符号按预期工作 [start:stop:step]:

    >>> v = NP.r_[.2, 1:25:7, 60.8]
    
    >>> v
      array([  0.2,   1. ,   8. ,  15. ,  22. ,  60.8])
    

    虽然如果将 虚数 用作第三个参数,切片符号的行为类似于 linspace

    >>> v = NP.r_[.2, 1:25:7j, 60.8]
    
    >>> v
      array([  0.2,   1. ,   5. ,   9. ,  13. ,  17. ,  21. ,  25. ,  60.8])
    


    否则,它的行为类似于 arange

    >>> v = NP.r_[.2, 1:25:7, 60.8]
    
    >>> v
      array([  0.2,   1. ,   8. ,  15. ,  22. ,  60.8])
    

    【讨论】:

    • 谢谢道格!这非常酷,而且它与 matlab 一样紧凑,还差两个字符。太棒了!
    • @vint-i-vuit 没问题。如果我的回答对您有帮助,请通过单击“复选标记”将其标记为“已接受”,当您将鼠标悬停在我的回答左上角的分数上时可见。 (或者如果另一个答案更有帮助,显然你会想要标记那个)。是的,它还有两个字符,但我认为这是值得的,因此 NumPy 可以为两个轴中的每一个提供一个函数来连接 (r_ & c_)。
    • 不知道,是的!我从所有帖子中学到了很多东西,它们都按我的意愿工作,但可能你的帖子最接近 MATLAB。谢谢大家!
    • c_ 不是按列对应的...它是特殊 r_ 调用的简写版本。您的 c_ 调用示例将不起作用。
    【解决方案3】:
    np.concatenate([[.2], linspace(1,60,60), [60.8]])
    

    【讨论】:

    • 该死的,真的!这行得通,谢谢拉尔斯曼。此外,每当我想做 a=[1:2:20] 之类的事情时,linspace 是唯一的选择吗?这意味着我不知道向量的最终大小,只知道步骤和起点/终点。
    • 多亏了 mgilson,我自己才发现它。答案是范围(开始、停止、步进)。太棒了!
    • 您也可以尝试np.arange(1,20,2),但要小心,因为此操作不包括范围内的最后一个数字(例如 array([ 1, 3, 5, 7, 9, 11, 13, 15、17、19]))。我忘记了 Matlab 是如何处理这个问题的,我早就把它从我的机器上删除了。
    • 很高兴知道!谢谢。据我所知,MATLAB 不断增加/减少,如果终点恰好在 a=[0:2:10] 等范围内,则 a 包含它。但是,如果不包括终点,例如在 a2=[1:2:10] 中,则 10 不包括在 a2 中。
    【解决方案4】:

    arange(0.2,60.8,0.2) 做你想做的事吗?

    http://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html

    【讨论】:

    • 确实! arange() 是我以后会经常使用的函数,也感谢分享。
    【解决方案5】:

    我有点喜欢构建您提到的这些分段范围的想法。如果你经常使用它们,也许是一个像

    这样的小功能
    import numpy as np
    
    def segrange(*args):
        result = []
        for arg in args:
            if hasattr(arg,'__iter__'):
                result.append(range(*arg))
            else:
                result.append([arg])
        return np.concatenate(result)
    

    给你

    >>> segrange(1., (2,5), (5,10,2))
    [ 1.  2.  3.  4.  5.  7.  9.]
    

    如果有就好了。虽然,我可能会使用 concatenate/hstack 来寻找答案。

    【讨论】:

    • 这是个好主意!从现在开始,我想我会尽量坚持使用 mgilson 回复中使用的 + 运算符,因为它是我发现最接近 matlab 的运算符,因此记住的工作量更少。但是我会看看在某些情况下执行该代码是否更方便:)
    • 如果我错了,请纠正我,但我认为isinstance(arg,list)type(arg) is list 更受欢迎。此外,您可以将整个 if 块缩短为 hasattr(arg,'__iter__')(并在您使用它时捕获各种其他可迭代对象)
    • 是的,你正确的 mgilson。但道格提出 _r 的回答取代了所有 ^^
    【解决方案6】:

    如果我对 matlab 的理解正确,您可以使用以下方法完成类似的操作:

    a=np.array([0.2]+list(range(1,61))+[60.8])
    

    但可能有更好的方法...如果您使用的是 python 2.X,list(range(1,61)) 可能只是 range(1,61)

    这是通过创建 3 个列表然后使用 + 运算符连接它们来实现的。

    你最初的尝试没有成功的原因是因为

    a=[ [0.2], np.linspace(1,60,60), [60.8] ] 创建一个列表列表——换句话说:

    a[0] == [0.2] #another list (length 1)
    a[1] == np.linspace(1,60,60) #an array (length 60)
    a[2] == [60.8] #another list (length 1)
    

    array 函数需要一个可迭代的序列,或者长度相同的序列序列。

    【讨论】:

    • 伟大的米吉尔森!这可能是最接近 MATLAB 的语法。仍然不如 a=[0.2,1:60,60.8] 紧凑,但很酷。非常感谢,我现在看得更清楚了。
    • 我想你会发现虽然numpy 中的很多东西都和 matlab 中一样简洁(还有一些东西稍微简洁一些),但也有很多东西不是t 非常简洁 -- 但是,总的来说,我发现代码更直观。
    • 据了解,到目前为止,获得的灵活性,特别是在绘图方面,非常值得语法的“不太简洁”。 :)
    【解决方案7】:

    看看np.r_。它基本上等同于其他人的建议,但如果你来自 matlab,它会更直观一些(如果你来自任何其他语言,它有点违反直觉)。

    例如,vector=[0.2,1:60,60.8]; 转换为:

    vector = np.r_[0.2, 1:61, 60.8]
    

    【讨论】:

      【解决方案8】:

      只想向其他从 MATLAB 转到 Numpy 的人指出,您可以构造一个带有冒号的 np.r_ 数组,然后用它来索引

      例如,如果你在 matlab 中有

      arr_ones = ones(10,10)
      

      或者在 Numpy 中

      arr_ones = np.ones([10,10])
      

      您可以在 Matlab 中只取第 1 到第 5 列以及第 7 列,如下所示:

      arr_ones(:,[1:5 7])
      

      在 Numpy 中做同样的事情并不(至少对我而言)直观。 这会给你一个“无效的语法”错误:

      arr_ones[:,[1:5,7]]
      

      但这是可行的:

      inds = np.r[1:5,]
      arr_ones[:,inds]
      

      我知道这在技术上并不是一个新的答案,但是在对矩阵进行索引时使用冒号构造数组在 Matlab 中似乎很自然,我敢打赌很多来到这个页面的人都会想知道这一点。 (我来这里不是问新问题。)

      【讨论】:

        【解决方案9】:

        使用 numpy.repeat() 的最简单方法 ||| numpy.tile()

        a = np.array([1,2,3,4,5])
        
        np.r_[np.repeat(a,3),np.tile(a,3)]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-19
          • 1970-01-01
          • 2017-12-30
          • 2015-12-16
          相关资源
          最近更新 更多