【问题标题】:numpy - Append to array without making a copynumpy - 追加到数组而不复制
【发布时间】:2016-08-19 07:02:57
【问题描述】:

Python 列表是指针,因此我可以执行以下操作:

a = []
b = a

b.append(1)

>>> print a, b
[1] [1]

使用 numpy 完成此行为的方法是什么?因为 numpy 的 append 创建了一个新数组。那就是:

a = np.array([])
b = a

b = np.append(b, 1)
>>> print a, b
[] [1.]

编辑 我要完成的工作:

我有一个大文本文件,我试图用re 解析它:根据文件中的标记,我想更改要附加到的数组。例如:

x = np.array([])
y = np.array([])

with open("./data.txt", "r") as f:
    for line in f:
        if re.match('x values', line):
            print "reading x values"
            array = x
        elif re.match('y', line):
            print "reading y values"
            array = y
        else:
            values = re.match("^\s+((?:[0-9.E+-]+\s*)*)", line)
            if values:
                np.append(array, values.groups()[0].split())

【问题讨论】:

  • 你不能那样做。 Numpy 数组在内存中连续分配,因此如果要调整它们的大小,则需要重新分配它们。附加到它们本质上是低效的。你能提供更多关于你的问题的背景吗?
  • @SvenMarnach 当然,现在已编辑。
  • @hansatz 以这种方式使用 NumPy 数组确实效率低下。收集列表中的数据,并在读取完文件后从列表中构建一个 Numpy 数组。
  • @SvenMarnach 好的,很高兴了解效率。那我就这样处理吧

标签: python arrays numpy


【解决方案1】:

所以简单的切换到列表追加可以写成:

x, y = [], []
with open("./data.txt", "r") as f:
    for line in f:
        if re.match('x values', line):
            print "reading x values"
            alist = x
        elif re.match('y', line):
            print "reading y values"
            alist = y
        else:
            values = re.match("^\s+((?:[0-9.E+-]+\s*)*)", line)
            if values:
                alist.append(values.groups()[0].split())

现在xy 都将是列表列表。如果子列表的大小都相同,您可以这样做

x_array = np.array(x)

得到一个二维数组。但是如果子列表的大小不同,这将产生一个dtype=object 的一维数组,这只不过是一个具有array 开销的列表。例如:

In [98]: np.concatenate([[1,2,3],[1,2]])
Out[98]: array([1, 2, 3, 1, 2])

In [99]: np.array([[1,2,3],[1,2]])
Out[99]: array([[1, 2, 3], [1, 2]], dtype=object)

In [100]: np.array([[1,2,3],[1,2,4]])
Out[100]: 
array([[1, 2, 3],
       [1, 2, 4]])

我预计使用这 2 个全局变量和列表字典 {"x": [], "y": []} 方法之间的时间差不会太大。全局变量也保存在字典中。

真正的问题是你是在列表还是数组中收集中间值。

【讨论】:

    【解决方案2】:

    根据您更新的问题,您似乎可以通过保留 numpy 数组的字典来轻松解决问题:

    x = np.array([])
    y = np.array([])
    Arrays = {"x": x, "y": y}
    
    with open("./data.txt", "r") as f:
        for line in f:
            if re.match('x values', line):
                print "reading x values"
                key = "x"
            elif re.match('y', line):
                print "reading y values"
                key = "y"
            else:
                values = re.match("^\s+((?:[0-9.E+-]+\s*)*)", line)
                if values:
                    Arrays[key] = np.append(Arrays[key], values.groups()[0].split())
    

    正如 Sven Marnach 在 cmets 和您的问题中指出的那样,这是对 numpy 数组的低效使用。

    更好的方法(同样,正如 Sven 指出的那样)是:

    Arrays = {"x": [], "y": []}
    
    with open("./data.txt", "r") as f:
        for line in f:
            if re.match('x values', line):
                print "reading x values"
                key = "x"
            elif re.match('y', line):
                print "reading y values"
                key = "y"
            else:
                values = re.match("^\s+((?:[0-9.E+-]+\s*)*)", line)
                if values:
                    Arrays[key].append(values.groups()[0].split())
    
    Arrays = {key: np.array(Arrays[key]) for key in Arrays}
    

    【讨论】:

    • 这段代码的运行时间是二次方的,所以不建议这样做。
    • 是否有特定原因在链接对象上使用字典。即b=a; b.append(1) 使用 python 列表时?
    • @hansatz,我发现字典更易读,代码更清晰。当两者都是可变的时,有很多人不理解a = b 的含义,所以我建议避免使用依赖于该行为的方法
    • @hansatz,字典很容易扩展到两个以上的项目
    【解决方案3】:

    看看numpy.hstack

    http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.hstack.html

    import numpy as np
    a = np.arange(0, 10, 1)
    b = np.array([5])
    np.hstack((a,b))
    

    返回array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 5])

    【讨论】:

    • 这对在不复制的情况下追加到数组有什么帮助?
    • 你可以做a = np.hstack((a,b))
    • 不过,这会创建一个副本,这是 OP 问题的重点。
    猜你喜欢
    • 2019-01-11
    • 1970-01-01
    • 2015-02-21
    • 2021-04-15
    • 1970-01-01
    • 2016-04-08
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    相关资源
    最近更新 更多