2017-01-12 7 views
2

У меня есть следующий список различных Numpy массивов:питона: перебор каждого элемента в параллельных вложенных списках

nparrays_list = [ 
    array([1, 2, 3, 4]) 
    array([5, 6, 7, 8]), 
    array([9, 10, 11, 12]) 
] 

Я хочу, чтобы перебрать весь список, не влияя на форме списка (т.е. я не» т хочет, чтобы сгладить список), чтобы получить следующий список Numpy массивов:

nparrays_list_Decimal = [ 
    array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')]) 
    array([Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')]), 
    array([Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')]) 
] 

Вот код, который я до сих пор:

import numpy as np 

nparrays_list_Decimal = [] 
for nparray in nparrays_list: 
    nparray_Decimal = np.array([D(str(item)) for item in nparray]) 
    nparrays_list_Decimal.append(nparray_Decimal) 

Моя проблема: я имею дело с тонны данных, поэтому создание нового списка не является идеальным (т. потерянная память). Есть ли простой способ перебора каждого элемента в исходном списке, даже если элементы находятся во вложенных списках (или массивах numpy в этом случае)?

+1

Как вы определили 'D'? И почему 'nparrays_list' не является массивом numpy? – Kasramvd

+0

Я думаю, вы могли бы хотя бы сохранить временный список, передав формат ''

+0

'D' означает Decimal. Позвольте мне изменить это, чтобы сделать его более понятным. И это 'nparrays_list', потому что это список массивов numpy. Я не нуждаюсь в контейнере, чтобы быть nparray, а также –

ответ

1

Поскольку вы будете иметь сиситемах аренда тип объекта внутри массива Numpy, вам нужно будет создавать новые массивы (если они не являются массивами dtype=object)

Вот демо самом деле вы не можете иметь смешанные типы в массиве Numpy:

>>> arr=np.array([1,2,3]) 
>>> arr 
array([1, 2, 3]) 
>>> arr[1]="string" 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: invalid literal for long() with base 10: 'string' 

Назначение типа Decimal для массива int не изменяет этот элемент на десятичный тип в массиве; arr[1] превращается в Decimal, но затем преобразуется обратно в междунар беззвучно:

>>> arr 
array([1, 2, 3]) 
>>> arr[1]=Decimal(arr[1]) 
>>> arr 
array([1, 2, 3]) 
>>> type(arr[1]) 
<type 'numpy.int64'> 

Вы можете сделать:

>>> nparrays_list_Decimal=[np.array([Decimal(e) for e in arr]) for arr in nparrays_list] 
>>> nparrays_list_Decimal 
[array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')], dtype=object), array([Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')], dtype=object), array([Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')], dtype=object)] 

Или просто придерживаться списка списков:

>>> LoL=[[Decimal(e) for e in arr] for arr in nparrays_list] 
>>> LoL 
[[Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')], [Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')], [Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')]] 

Если память - ваша забота, (a ой, как правило, вам не нужно беспокоиться об этом так много скромных массивах), вы можете сделать больше памятей эффективного преобразования путем удаления подмассива, как конвертировать их:

from collections import deque 

nparrays_list=deque(LoA) # the List of Arrays is garbage collected.. 
nparrays_list_Decimal=[] 
while nparrays_list: 
    # each sublist is garbage collected after being popped and iterated 
    nparrays_list_Decimal.append(np.array([Decimal(e) for e in nparrays_list.popleft()])) 

>>> nparrays_list_Decimal 
[array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')], dtype=object), array([Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')], dtype=object), array([Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')], dtype=object)] 
+0

Понятия списка достаточно. Благодарю. И исходя из вашего сообщения и сообщения hpaulj, это звучит так, будто память здесь не является ограничивающим фактором. –

0

Чтобы перебрать все элементы, вы можете сделать вложенный цикл, как этот.

nparrays_list = [ 
     array([1, 2, 3, 4]), 
     array([5, 6, 7, 8]), 
     array([9, 10, 11, 12]) 
    ] 

for arr in nparrays_list: 
    for i, item in enumerate(arr): 
    arr[i] = Decimal(str(item)) 
+0

Когда я пытаюсь 'item = Decimal (str (item))' в последней строке ничего не происходит. Как я могу использовать это для преобразования всех значений в десятичные объекты? –

+0

@ jcmetz21 Обновлен мой ответ для этого – gipsy

+0

Это не преобразует элементы в объекты 'Decimal'. См. Сообщение hpaulj или мое сообщение. – dawg

1

Может быть что-то вроде этого

import numpy as np 

nparrays_list_Decimal = [list(map(float, lst)) for lst in nparrays_list] 

Edit:

From the Python Documentation on Decimals

Чтобы использовать десятичные попробовать этот

from decimal import * 
nparrays_list_Decimal = [list(map(Decimal, lst)) for lst in nparrays_list] 
+0

Как я могу использовать это для преобразования чисел в десятичные объекты (что мне нужно для большей точности)? Поплавки слишком неточны –

+1

Добавлен десятичный код для вас –

1
nparrays_list = [ 
    array([1, 2, 3, 4]) 
    array([5, 6, 7, 8]), 
    array([9, 10, 11, 12]) 
] 

Не беспокойтесь о том, новые списки. Списки содержат только указатели на объекты в другом месте в памяти. В этом случае список занимает только 3 целых числа. Компоненты занимают память - это массивы с 4-х элементными буферами данных.

nparrays_list_Decimal = [ 
    array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')]), 
    array([Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')]), 
    array([Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')]) 
] 

- еще один небольшой список, с 3 указателями. Вы могли бы вернуть эти указатели к оригиналу nparray_list, но почему? Просто чтобы сохранить 3 целых числа?

Но что показательно, что новые массивы не совместимы, память мудрая, с оригиналами:

array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')]) 

является массивом объектов DTYPE. Это похоже на список с указателями на те Decimal(n') объектов, где в памяти. Это должен быть новый массив; он не может заменить np.int32 предметов в оригинале array([1,2,3,4]).

Почему вы не просто идти от

nparrays_list = [ 
    [1, 2, 3, 4], 
    [5, 6, 7, 8], 
    [9, 10, 11, 12] 
] 

к:

nparrays_list_Decimal = [ 
    [Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')], 
    [Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')], 
    [Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')] 
] 

Другими словами, придерживаться списков списков. Является ли массив объектов Decimal более полезными, чем список того же самого?

===============

Поскольку Decimal определяет множество математических операций, можно выполнить некоторый массив математику на массиве Decimal объектов:

In [482]: arr = np.array([Decimal(i) for i in range(1,4)]) 
In [483]: arr 
Out[483]: array([Decimal('1'), Decimal('2'), Decimal('3')], dtype=object) 
In [484]: arr + 1 
Out[484]: array([Decimal('2'), Decimal('3'), Decimal('4')], dtype=object) 
In [485]: 1/arr 
Out[485]: 
array([Decimal('1'), Decimal('0.5'), 
     Decimal('0.3333333333333333333333333333')], dtype=object) 

По скорости последнего утверждения в основном так же, как:

np.array([1/i for i in arr]) 

это будет медленнее, чем 1/np.arange(1,4).

====================

Вы можете получить небольшое улучшение скорости, делая десятичного массив с:

In [503]: np.frompyfunc(Decimal,1,1)(np.arange(3)) 
Out[503]: array([Decimal('0'), Decimal('1'), Decimal('2')], dtype=object) 
In [504]: np.frompyfunc(Decimal,1,1)(np.arange(12).reshape(3,4)) 
Out[504]: 
array([[Decimal('0'), Decimal('1'), Decimal('2'), Decimal('3')], 
     [Decimal('4'), Decimal('5'), Decimal('6'), Decimal('7')], 
     [Decimal('8'), Decimal('9'), Decimal('10'), Decimal('11')]], dtype=object) 

В в других тестах я обнаружил, что frompyfunc имеет более скромное (например, 2x) улучшение скорости по сравнению с более явными итерационными выражениями. Это также имеет то преимущество, что позволяет легко обрабатывать многомерные массивы. Он возвращает массив object. Иногда это проблема; здесь все в порядке.

In [509]: timeit np.frompyfunc(Decimal,1,1)(np.arange(2000)) 
1000 loops, best of 3: 752 µs per loop 
In [510]: timeit np.array([Decimal(str(i)) for i in np.arange(2000)]) 
100 loops, best of 3: 17.1 ms per loop 
In [515]: timeit np.array([Decimal(i) for i in range(2000)]) 
100 loops, best of 3: 7.39 ms per loop 
In [525]: timeit np.array([Decimal(i.item()) for i in np.arange(2000)]) 
100 loops, best of 3: 11.3 ms per loop 

Я задавался вопросом, почему вы использовали str(i). Но потом я обнаружил, что Decimal может принимать только некоторые из np.dtypes (не np.int32). Моя догадка является frompyfunc использует item() или эквивалент для получения скаляров Python:

In [523]: np.frompyfunc(Decimal,1,1)(np.arange(2)) 
Out[523]: array([Decimal('0'), Decimal('1')], dtype=object) 
In [524]: np.array([Decimal(i.item()) for i in np.arange(2)]) 
Out[524]: array([Decimal('0'), Decimal('1')], dtype=object) 

frompyfunc должен делать эквивалент i.item() для создания Python скаляра из np.int32 объекта.

+0

Мне нужен контейнер np.array, потому что я выполняю математические операции, которые намного упрощаются с помощью модуля numpy –

+0

Да, я добавил несколько примеров, где полезно использовать массив объектов. В любом случае, я не думаю, что вы можете улучшить скорость или использовать память. Вы будете иметь 1000-ый из десятичных объектов и 1000 указателей на эти объекты, независимо от структуры контейнера. – hpaulj

+0

Я добавил демонстрацию использования 'frompyfunc' для облегчения создания массива' Десятичный'. – hpaulj

0

Я не numpy, но следующие может дать вам направление, чтобы решить вашу проблему:

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> import array 
>>> array_list = [ 
    array.array('q', [1, 2, 3, 4]), 
    array.array('q', [5, 6, 7, 8]), 
    array.array('q', [9, 10, 11, 12]) 
    ] 
>>> def iterate(iterable): 
    for index_a, value_a in enumerate(iterable): 
     try: 
      for index_b, value_b in iterate(value_a): 
       yield [index_a] + index_b, value_b 
     except TypeError: 
      yield [index_a], value_a 


>>> for index, value in iterate(array_list): 
    print(value, 'is at', index) 


1 is at [0, 0] 
2 is at [0, 1] 
3 is at [0, 2] 
4 is at [0, 3] 
5 is at [1, 0] 
6 is at [1, 1] 
7 is at [1, 2] 
8 is at [1, 3] 
9 is at [2, 0] 
10 is at [2, 1] 
11 is at [2, 2] 
12 is at [2, 3] 
>>> 

Чтобы завершить решение проблемы, автоматическое приведение или преобразование типов может быть поддержано:

>>> def iterate(iterable, cast): 
    for index_a, value_a in enumerate(iterable): 
     try: 
      for index_b, value_b in iterate(value_a, cast): 
       yield [index_a] + index_b, value_b 
     except TypeError: 
      yield [index_a], cast(value_a) 


>>> import decimal 
>>> for index, value in iterate(array_list, decimal.Decimal): 
    print(repr(value), 'came from', index) 


Decimal('1') came from [0, 0] 
Decimal('2') came from [0, 1] 
Decimal('3') came from [0, 2] 
Decimal('4') came from [0, 3] 
Decimal('5') came from [1, 0] 
Decimal('6') came from [1, 1] 
Decimal('7') came from [1, 2] 
Decimal('8') came from [1, 3] 
Decimal('9') came from [2, 0] 
Decimal('10') came from [2, 1] 
Decimal('11') came from [2, 2] 
Decimal('12') came from [2, 3] 
>>> 
+0

Мне обязательно нужно будет изучить эти итерационные функции. благодаря –

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

  • Нет связанных вопросов^_^