Wie erstelle ich ein numpy Array von Strings beliebiger Länge?

75

Ich bin ein absoluter Neuling in Python, aber es scheint, dass eine bestimmte Zeichenfolge (effektiv) eine beliebige Länge haben kann. dh du kannst ein nehmen string strund es weiter ergänzen : str += "some stuff...". Gibt es eine Möglichkeit, ein Array solcher Zeichenfolgen zu erstellen?

Wenn ich das versuche, speichert jedes Element nur ein einziges Zeichen

strArr = numpy.empty(10, dtype='string')
for i in range(0,10)
    strArr[i] = "test"

Andererseits weiß ich, dass ich ein Array von Strings bestimmter Länge initialisieren kann, d. H.

strArr = numpy.empty(10, dtype='s256')

Hier können 10 Zeichenfolgen mit bis zu 256 Zeichen gespeichert werden.

DilithiumMatrix
quelle

Antworten:

125

Sie können dies tun, indem Sie ein Array von erstellen dtype=object. Wenn Sie versuchen, einem normalen Numpy-Array eine lange Zeichenfolge zuzuweisen, wird die Zeichenfolge abgeschnitten:

>>> a = numpy.array(['apples', 'foobar', 'cowboy'])
>>> a[2] = 'bananas'
>>> a
array(['apples', 'foobar', 'banana'], 
      dtype='|S6')

Bei Verwendung erhalten dtype=objectSie jedoch ein Array von Python-Objektreferenzen. So können Sie alle Verhaltensweisen von Python-Strings haben:

>>> a = numpy.array(['apples', 'foobar', 'cowboy'], dtype=object)
>>> a
array([apples, foobar, cowboy], dtype=object)
>>> a[2] = 'bananas'
>>> a
array([apples, foobar, bananas], dtype=object)

Da es sich um ein Array von Objekten handelt, können Sie dem Array jede Art von Python-Objekt zuweisen :

>>> a[2] = {1:2, 3:4}
>>> a
array([apples, foobar, {1: 2, 3: 4}], dtype=object)

Dies macht jedoch viele Vorteile der Verwendung von numpy rückgängig, was so schnell ist, weil es auf großen zusammenhängenden Blöcken von Rohspeicher funktioniert. Das Arbeiten mit Python-Objekten erhöht den Overhead. Ein einfaches Beispiel:

>>> a = numpy.array(['abba' for _ in range(10000)])
>>> b = numpy.array(['abba' for _ in range(10000)], dtype=object)
>>> %timeit a.copy()
100000 loops, best of 3: 2.51 us per loop
>>> %timeit b.copy()
10000 loops, best of 3: 48.4 us per loop
senderle
quelle
1
Danke, Ihr erstes Beispiel ist besonders hilfreich - ich hätte dieses Verhalten nie erraten! Ich mache mir keine Sorgen um die Geschwindigkeit dieses Objekts, daher sollte ein langsamerer Zugriff in Ordnung sein.
DilithiumMatrix
1
Gute Antwort. Ich habe einen Link mit Demo in eine Python-Notizbuchseite eingefügt, an der ich gerade über die Erstellung von Numpy-Arrays arbeite.
John Lockwood
@senderle Wenn ein Array mit objectdtype ist, schlägt dies np.fromstring(arr.tostring())mit fehl numpy Cannot create an object array from a string. Irgendwelche Ideen, um das zu lösen?
Youkaichao
@ 游 凯 超 hmm. Das ist eine schwierige Frage. Es ist keine völlige Überraschung, da Numpy wirklich nicht für die Arbeit mit Python-Objekten ausgelegt ist. Es ist eher eine Abkürzung als eine richtige Verwendung von Numpy. Es gibt also keinen wirklichen Grund für sie, solche Eckfälle zu unterstützen. Mein Ansatz wäre wahrscheinlich, die maximale Länge der Zeichenfolge zu ermitteln und ein Standard-Char-Array mit fester Breite zu verwenden.
senderle
@ 游 凯 超 Wenn Sie Zeichenfolgen als Zeilenbeschriftungen oder Spaltenüberschriften verwenden möchten, sollten Sie sich auch strukturierte Arrays ansehen .
senderle
17

Sie können den Objektdatentyp verwenden:

>>> import numpy
>>> s = numpy.array(['a', 'b', 'dude'], dtype='object')
>>> s[0] += 'bcdef'
>>> s
array([abcdef, b, dude], dtype=object)
jterrace
quelle