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