Эффективный способ создания numpy массива кортежей фиксированного размера из байтов

#python #numpy

#python #numpy

Вопрос:

Я пытаюсь преобразовать байты в числовой массив кортежей фиксированного размера (2 или 3 удвоения), и это должен быть 1d массив. Что мне удалось получить, так это:
values = np.fromstring(data, (np.double, (n,))) — это дает мне 2d массив с формой (105107, 2)

 array([[0.03171165, 0.03171165],
       [0.03171165, 0.03171165],
       [0.03020949, 0.03020949],
       ...,
       [0.05559354, 0.16173067],
       [0.12667986, 0.04522982],
       [0.14062567, 0.11422881]])
  

values = np.fromstring(data, [('dt', np.double, (n,))]) — это дает мне 1d массив с формой (105107,), но массив содержит кортежи, содержащие массив с двумя удвоениями

 array([([0.03171165, 0.03171165],), ([0.03171165, 0.03171165],),
       ([0.03020949, 0.03020949],), ..., ([0.05559354, 0.16173067],),
       ([0.12667986, 0.04522982],), ([0.14062567, 0.11422881],)],
      dtype=[('dt', '<f8', (2,))])
  

есть ли какой-либо эффективный способ получить 1d массив, подобный этому?:

 array([(0.03171165, 0.03171165),
       (0.03171165, 0.03171165),
       (0.03020949, 0.03020949),
       ...,
       (0.05559354, 0.16173067),
       (0.12667986, 0.04522982),
       (0.14062567, 0.11422881)])
  

Комментарии:

1. Хотя в dt случае используются () , это не кортежи. Это структурированный массив. Зачем вам нужны кортежи? Какой dtype должен иметь массив? Почему?

Ответ №1:

Нет, я не знаю эффективного способа, но поскольку до сих пор никто вообще не опубликовал никакого ответа, вот способ, который, по крайней мере, дает вам желаемый результат. Однако эффективным это не является.

 values = np.fromstring(data, (np.double, (n,)))
x = np.empty(values.shape[0], dtype=np.object)
for i, a in enumerate(values):
    x[i] = tuple(a)
  

Я бы добавил, что если у вас есть массив объектов, это настолько сводит на нет преимущества использования векторизации в numpy, что вы могли бы просто использовать список вместо этого:

 values = np.fromstring(data, (np.double, (n,)))
x = [tuple(a) for a in values]
  

Возможный альтернативный подход к созданию массива кортежей — не уверен, что это быстрее — состоял бы в том, чтобы пройти через такой список и преобразовать его обратно в массив таким образом, чтобы намеренно прервать преобразование в хороший обычный 2-d массив, который в противном случае сделал бы numpy:

 values = np.fromstring(data, (np.double, (n,)))
x = [tuple(a) for a in values]
x.append(None)
y = np.array(x)[:-1]
  

Ответ №2:

Я уже решил проблему, используя этот код:

 names = ['d{i}'.format(i=i) for i in range(n)]
value = np.fromstring(data, {
    'names': names,
    'formats': [np.double] * n
})
  

Комментарии:

1. Опять же, это не кортежи. Это структурированный массив с n полями. Это хороший результат, но вы должны использовать правильную терминологию.