Wenn Sie ein 1d-Array in Python erstellen, ist es dann sinnvoll, das NumPy-Paket zu verwenden?
Antworten
Zu viele Anzeigen?Es hängt alles davon ab, was Sie mit dem Array vorhaben. Wenn Sie nur Arrays von einfachen Datentypen erstellen und E/A durchführen wollen, ist die Array Modul reicht völlig aus.
Wenn Sie hingegen irgendeine Art von numerischen Berechnungen durchführen wollen, bietet das Array-Modul keine Hilfe. NumPy (und SciPy ) bieten Ihnen eine Vielzahl von Operationen zwischen Arrays und speziellen Funktionen, die nicht nur für wissenschaftliche Arbeiten nützlich sind, sondern auch für fortgeschrittene Bildbearbeitung oder allgemein für alles, wo Sie effiziente Berechnungen mit großen Datenmengen durchführen müssen.
Numpy ist auch viel flexibler, z.B. unterstützt es Arrays aller Arten von Python-Objekten und ist auch in der Lage, "nativ" mit Ihren eigenen Objekten zu interagieren, wenn diese der Array-Schnittstelle .
Kleines Bootstrapping zugunsten derjenigen, die dies nützlich finden könnten (im Anschluss an die ausgezeichnete Antwort von @dF.):
import numpy as np
from array import array
# Fixed size numpy array
def np_fixed(n):
q = np.empty(n)
for i in range(n):
q[i] = i
return q
# Resize with np.resize
def np_class_resize(isize, n):
q = np.empty(isize)
for i in range(n):
if i>=q.shape[0]:
q = np.resize(q, q.shape[0]*2)
q[i] = i
return q
# Resize with the numpy.array method
def np_method_resize(isize, n):
q = np.empty(isize)
for i in range(n):
if i>=q.shape[0]:
q.resize(q.shape[0]*2)
q[i] = i
return q
# Array.array append
def arr(n):
q = array('d')
for i in range(n):
q.append(i)
return q
isize = 1000
n = 10000000
Die Ausgabe ergibt:
%timeit -r 10 a = np_fixed(n)
%timeit -r 10 a = np_class_resize(isize, n)
%timeit -r 10 a = np_method_resize(isize, n)
%timeit -r 10 a = arr(n)
1 loop, best of 10: 868 ms per loop
1 loop, best of 10: 2.03 s per loop
1 loop, best of 10: 2.02 s per loop
1 loop, best of 10: 1.89 s per loop
Es scheint, dass array.array etwas schneller ist und die 'api' Ihnen einige Probleme erspart, aber wenn Sie mehr als nur das Speichern von Doubles benötigen, dann ist numpy.resize doch keine schlechte Wahl (wenn es richtig verwendet wird).
Für Speicherzwecke sind sowohl numpy array als auch array.array vergleichbar. Hier ist der Code für den Benchmark für beide, der die Speichergröße von unsigned integer von 4 Bytes vergleicht. Es können auch andere Datentypen für den Vergleich verwendet werden. Daten von list und tuple werden ebenfalls zum Vergleich hinzugefügt
import sys
import numpy as np
from array import array
def getsizeof_deep(obj, seen=None):
"""Recursively finds size of objects"""
size = sys.getsizeof(obj)
if seen is None:
seen = set()
obj_id = id(obj)
if obj_id in seen:
return 0
# Important mark as seen *before* entering recursion to gracefully handle
# self-referential objects
seen.add(obj_id)
if isinstance(obj, dict):
size += sum([getsizeof_deep(v, seen) for v in obj.values()])
size += sum([getsizeof_deep(k, seen) for k in obj.keys()])
elif hasattr(obj, '__dict__'):
size += getsizeof_deep(obj.__dict__, seen)
elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):
size += sum([getsizeof_deep(i, seen) for i in obj])
return size
print("size per element for list, tuple, numpy array, array.array:===============")
for i in range(1, 100, 5):
aa = list(range(i))
n = len(aa)
list_size = getsizeof_deep(aa)
tup_aa = tuple(aa)
tup_size = getsizeof_deep(tup_aa)
nparr = np.array(aa, dtype='uint32')
np_size = getsizeof_deep(nparr)
arr = array('I', aa)#4 byte unsigned integer(in ubuntu)
arr_size = getsizeof_deep(arr)
print('number of element:%s, list %.2f, tuple %.2f, np.array %.2f, arr.array %.2f' % \
(len(aa), list_size/n, tup_size/n, np_size/n, arr_size/n))
Dies führte zu folgendem Ergebnis auf meinem Rechner:
size per element for list, tuple, numpy array, array.array:===============
number of element:1, list 88.00, tuple 72.00, np.array 136.00, arr.array 92.00
number of element:6, list 44.67, tuple 42.00, np.array 49.33, arr.array 42.00
number of element:11, list 40.73, tuple 39.27, np.array 41.45, arr.array 37.45
number of element:16, list 39.25, tuple 38.25, np.array 38.50, arr.array 35.75
number of element:21, list 38.48, tuple 37.71, np.array 36.95, arr.array 34.86
number of element:26, list 38.00, tuple 37.38, np.array 36.00, arr.array 34.31
number of element:31, list 37.68, tuple 37.16, np.array 35.35, arr.array 33.94
number of element:36, list 37.44, tuple 37.00, np.array 34.89, arr.array 33.67
number of element:41, list 37.27, tuple 36.88, np.array 34.54, arr.array 33.46
number of element:46, list 37.13, tuple 36.78, np.array 34.26, arr.array 33.30
number of element:51, list 37.02, tuple 36.71, np.array 34.04, arr.array 33.18
number of element:56, list 36.93, tuple 36.64, np.array 33.86, arr.array 33.07
number of element:61, list 36.85, tuple 36.59, np.array 33.70, arr.array 32.98
number of element:66, list 36.79, tuple 36.55, np.array 33.58, arr.array 32.91
number of element:71, list 36.73, tuple 36.51, np.array 33.46, arr.array 32.85
number of element:76, list 36.68, tuple 36.47, np.array 33.37, arr.array 32.79
number of element:81, list 36.64, tuple 36.44, np.array 33.28, arr.array 32.74
number of element:86, list 36.60, tuple 36.42, np.array 33.21, arr.array 32.70
number of element:91, list 36.57, tuple 36.40, np.array 33.14, arr.array 32.66
number of element:96, list 36.54, tuple 36.38, np.array 33.08, arr.array 32.62