2013-06-05 9 views
6

Esiste un modo nativo NumPy per convertire una serie di rappresentazioni di stringa di booleani ad esempio:Numpy Convert String Rappresentanza della matrice booleana per array booleano

['True','False','True','False'] 

Per una matrice reale booleano posso usare per il mascheramento/indicizzazione? Potrei fare un ciclo for attraverso e ricostruire l'array ma per array di grandi dimensioni questo è lento.

+0

Si tratta di un array di stringhe NumPy (se esiste una cosa del genere) o un array di stringhe Python? – Eric

+0

È una serie di stringhe numpy - strano, lo so. – Newmu

+1

@Newmu - Penso che la soluzione a questo è evitare di ottenere un array di rappresentazioni di stringhe in primo luogo. Come sei arrivato da quell'array? Forse è qui che dovremmo iniziare a cercare di ottimizzare questo ... – mgilson

risposta

6

Si dovrebbe essere in grado di fare un confronto booleano, IIUC, se il dtype è una stringa o object:

>>> a = np.array(['True', 'False', 'True', 'False']) 
>>> a 
array(['True', 'False', 'True', 'False'], 
     dtype='|S5') 
>>> a == "True" 
array([ True, False, True, False], dtype=bool) 

o

>>> a = np.array(['True', 'False', 'True', 'False'], dtype=object) 
>>> a 
array(['True', 'False', 'True', 'False'], dtype=object) 
>>> a == "True" 
array([ True, False, True, False], dtype=bool) 
+0

+1 - Quindi ... semplice. – mgilson

+0

Le meraviglie della trasmissione? Inoltre è veloce (20 volte più veloce dell'altra risposta). – Newmu

+0

@Newmu E internamento stringa, se non mi sbaglio (almeno, tutti gli elementi in 'a' che sono' 'True'' hanno lo stesso valore per 'id()', che è anche il caso per tutti' ' Gli elementi di False' [sebbene stranamente, 'is' non sembra funzionare per questi elementi, infatti non funziona nemmeno quando si verifica una voce contro se stessa. 'A [0] è a [0]' restituisce 'False ', anche se' id (a [0]) == id (a [0]) 'restituisce' True']) Credo che internare sia il motivo per cui i controlli di uguaglianza qui sono molto più veloci di 'numpy.char.startswith() 'anche se le funzioni in' numpy.char' dovrebbero eseguire operazioni di stringa veloci su array numpy. – JAB

0

È abbastanza buono?

my_list = ['True', 'False', 'True', 'False'] 
np.array(x == 'True' for x in my_list) 

non è nativo, ma se si sta iniziando con un elenco non nativo in ogni caso, in realtà non dovrebbe importare.

+1

Non funzionerà come scritto perché numpy non funziona bene con le espressioni del generatore. – DSM

+0

Il boxing come una lista comp funziona ma è 20 volte più lento della risposta di DSM per gli array con più di qualche migliaio di valori. – Newmu

2

Ho trovato un metodo che è anche più veloce di DSM, prendendo ispirazione da Eric, anche se il miglioramento si vede meglio con elenchi di valori più piccoli; a valori molto grandi, il costo dell'iterazione stessa supera il vantaggio dell'esecuzione del test di verità durante la creazione dell'array numpy piuttosto che dopo. Test con entrambi is e == (per le situazioni in cui le stringhe sono internate rispetto a quando potrebbero non esserlo, come is non funzionerebbe con stringhe non internate. Come 'True' probabilmente sarà un letterale nello script che dovrebbe essere internato, sebbene) ha dimostrato che mentre la mia versione con == era più lenta rispetto a is, era ancora molto più veloce della versione di DSM. configurazione

prova:

import timeit 
def timer(statement, count): 
    return timeit.repeat(statement, "from random import choice;import numpy as np;x = [choice(['True', 'False']) for i in range(%i)]" % count) 

>>> stateIs = "y = np.fromiter((e is 'True' for e in x), bool)" 
>>> stateEq = "y = np.fromiter((e == 'True' for e in x), bool)" 
>>> stateDSM = "y = np.array(x) == 'True'" 

Con 1000 voci, le dichiarazioni più veloci prendere circa il 66% del tempo del DSM di:

>>> timer(stateIs, 1000) 
[101.77722641656146, 100.74985342340369, 101.47228618107965] 
>>> timer(stateEq, 1000) 
[112.26464996250706, 112.50754567379681, 112.76057346127709] 
>>> timer(stateDSM, 1000) 
[155.67689949529995, 155.96820504501557, 158.32394669279802] 

Per gli array di stringhe più piccoli (nell'ordine delle centinaia piuttosto che migliaia), il tempo trascorso è inferiore al 50% del DSM di:

>>> timer(stateIs, 100) 
[11.947757485669172, 11.927990253608186, 12.057855628259858] 
>>> timer(stateEq, 100) 
[13.064947253943501, 13.161545451986967, 13.30599035623618] 
>>> timer(stateDSM, 100) 
[31.270060799078237, 30.941749748808434, 31.253922641324607] 

Un po 'oltre il 25% del DSM di quando fatto con 50 articoli per lista:

>>> timer(stateIs, 50) 
[6.856538342483873, 6.741083326021908, 6.708402786859551] 
>>> timer(stateEq, 50) 
[7.346079345032194, 7.312723444475523, 7.309259899921017] 
>>> timer(stateDSM, 50) 
[24.154247576229864, 24.173593700599667, 23.946403452288905] 

Per 5 voci, circa l'11% del DSM di:

>>> timer(stateIs, 5) 
[1.8826215278058953, 1.850232652068371, 1.8559381315990322] 
>>> timer(stateEq, 5) 
[1.9252821868467436, 1.894011299061276, 1.894306935199893] 
>>> timer(stateDSM, 5) 
[18.060974208809057, 17.916322392367874, 17.8379771602049] 
+1

Hai notato che sono tutti 'True' nel risultato? :-P – mgilson

+0

.. le stringhe non vuitton sono vere, anche se sono "false" .. – DSM

+0

@DSM La mia nuova risposta sembra essere un grande miglioramento rispetto alla mia precedente. – JAB

Problemi correlati