python:遍历并行嵌套列表中的每个项目

时间:2017-01-12 18:21:38

标签: python arrays numpy iteration

我有以下各种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数组)?

5 个答案:

答案 0 :(得分:1)

也许是这样的

import numpy as np

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

编辑:

From the Python Documentation on Decimals

要使用小数,请尝试此

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

答案 1 :(得分: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类型分配给整数数组不会将该元素更改为数组中的十进制类型; arr[1]转换为Decimal,但后来无声地转换回int:

>>> 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')]]

如果您关心内存,(并且通常您不需要担心使用适度的数组),您可以通过删除子阵列来进行更高效的内存转换转换它们:

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

答案 2 :(得分: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)

Speedwise这最后一句话基本上与:

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

它会比1/np.arange(1,4)慢。

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

通过使用:

创建Decimal数组,可以提高速度
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比更明确的迭代表达式具有适度(例如2倍)的速度提升。它还具有无缝处理多维数组的优点。它返回一个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()等效,才能从np.int32对象生成Python标量。

答案 3 :(得分:0)

要遍历每个项目,您可以像这样执行嵌套for循环。

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

答案 4 :(得分: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]
>>>