2016-04-25 6 views
1

списков Python являются указатели, так что я могу сделать следующее:NumPy - добавление в массив, не создавая копию

a = [] 
b = a 

b.append(1) 

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

Какой путь для достижения этой проблемы с помощью NumPy? Поскольку append numpy создает новый массив. То есть:

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

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

EDIT То, что я пытаюсь выполнить:

У меня есть большой текстовый файл, который я пытаюсь разобрать с 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()) 
+2

Вы не можете этого сделать. Массивы массивов выделены последовательно в памяти, поэтому их необходимо перераспределить, если вы хотите изменить их размер. Добавление к ним по своей сути неэффективно. Можете ли вы дать немного больше контекста вашей проблемы? –

+2

Возможный дубликат [Как расширить массив на месте в Numpy?] (Http://stackoverflow.com/questions/13215525/how-to-extend-an-array-in-place-in-numpy) – wnnmaw

+0

@ SvenMarnach Sure, отредактированный сейчас. – Ben

ответ

1

на основе обновленной вопрос, он выглядит, как вы можете ловко решить эту проблему, сохраняя словарь массивов 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()) 

Как Свен Марнах указывает в комментариях как здесь, так и на ваш вопрос, это неэффективное использование массивов numpy.

Лучший подход (опять же, как Свен указывает) будет:

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} 
+2

Этот код будет иметь квадратичное время выполнения, поэтому не рекомендуется делать это таким образом. –

+0

Есть ли конкретная причина использовать словарь по связанным объектам. т.е. b = a; b.append (1) 'при использовании списков python? – Ben

+0

@hansatz, я нахожу словарь более понятным и понятным. Есть много людей, которые не понимают последствий «a = b», когда обе изменяемы, поэтому я бы предложил избегать метода, который полагается на это поведение – wnnmaw

-1

Посмотрите 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])

+0

Как это помогает с добавлением массива без создания копии? –

+0

Вы можете сделать 'a = np.hstack ((a, b))' – Simon

+3

Это создаст копию, хотя, чтобы избежать всего этого вопроса OP. –

0

Так просто переключение в список Append можно записать в виде:

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()) 

Теперь как x и y будут списки списков. Если подсписчики одинакового размера, вы можете сделать

x_array = np.array(x) 

, чтобы получить 2-мерный массив. Но если подсписки отличаются по размеру, это создаст 1d-массив из 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": []} захода на посадку. Глобальные переменные хранятся и в словаре.

Настоящая проблема заключается в том, собираете ли вы промежуточные значения в списках или массивах.

Смежные вопросы