2013-06-05 10 views
6

Czy istnieje rodzimy numpy sposobem konwersji tablicę reprezentacji smyczkowych logicznych npNumpy Konwersja String Przedstawienie logicznej tablicy do logicznego Array

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

do rzeczywistej logicznej tablicy można używać do maskowania/indeksowania? Mogłem wykonać pętlę for i przebudować tablicę, ale w przypadku dużych tablic jest to powolne.

+0

Czy to numpy tablicy string (jeśli coś takiego istnieje) lub tablicy pyton strun? – Eric

+0

To tablica szumów - dziwne, wiem. – Newmu

+1

@Newmu - Myślę, że rozwiązaniem tego problemu jest uniknięcie sytuacji, w której w pierwszej kolejności powstanie tablica reprezentacji napisów. Jak doszedłeś do tej tablicy? Może właśnie tam powinniśmy zacząć szukać optymalizacji tego ... – mgilson

Odpowiedz

6

Powinieneś być w stanie zrobić logiczną porównania, IIUC, czy dtype jest ciągiem lub 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) 

lub

>>> 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 - Więc ... proste. – mgilson

+0

Cuda nadawania? Jest też szybki (20 razy szybszy niż w drugiej odpowiedzi). – Newmu

+0

@Newmu I string interning, jeśli się nie mylę (przynajmniej wszystkie elementy w 'a', które są' 'True'' mają tę samą wartość dla 'id()', co jest również w przypadku wszystkich '' Fałszywe elementy (choć dziwne, 'jest' nie wydaje się działać dla tych elementów, w rzeczywistości nie działa, nawet gdy testujesz wpis względem siebie.' A [0] to [0] 'zwraca' Fałsz ', nawet jeśli' id (a [0]) == id (a [0]) 'zwraca' True']) Wierzę, że interning jest przyczyną, dla której sprawdzanie równości jest o wiele szybsze niż 'numpy.char.startswith() 'chociaż funkcje w' numpy.char' mają wykonywać szybkie operacje na ciągach numpy. – JAB

0

Czy to wystarczy?

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

To nie jest natywna, ale jeśli zaczynasz z listą nierodzime tak czy inaczej, to naprawdę nie powinno mieć znaczenia.

+1

To nie zadziała tak, jak napisano, ponieważ numpy nie gra dobrze z wyrażeń generatora. – DSM

+0

Boks jako kompilator listy działa, ale jest 20 razy wolniejszy niż odpowiedź DSM dla tablic z więcej niż kilkoma tysiącami wartości. – Newmu

2

znalazłem metodę, która jest nawet szybciej niż DSM, czerpiąc inspirację z Erica, choć poprawa najlepiej widać na mniejszych listach wartości; przy bardzo dużych wartościach koszt samej iteracji zaczyna przewyższać przewagę wykonywania testu prawdy podczas tworzenia tablicy numpy zamiast późniejszej. Testowanie zarówno z is jak i == (w sytuacjach, w których łańcuchy są internowane, a nie kiedy, mogą nie być, ponieważ is nie działałyby z nie-internowanymi łańcuchami. Ponieważ 'True' prawdopodobnie będzie literałem w skrypcie, powinno być internowane, chociaż) pokazał, że podczas gdy moja wersja z == była wolniejsza niż z is, wciąż była znacznie szybsza niż wersja DSM. Konfiguracja

Test:

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'" 

z 1000 elementów, tym szybciej oświadczenia zajmuje około 66% czas DSM:

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

Dla mniejszych tablic string (w setkach, a nie tysiącach) czas, jaki upłynął jest mniejszy niż 50% DSM:

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

nieco ponad 25% po zakończeniu DSM z 50 pozycji na liście:

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

dla 5 pozycji, około 11% z DSM:

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

Czy zauważyłeś, że wszystkie są "Prawdziwe" w wyniku? :-P – mgilson

+0

.. niepuste napisy są prawdziwe, nawet jeśli są "fałszywe" .. – DSM

+0

@DSM Moja nowa odpowiedź wydaje się być świetnym ulepszeniem w stosunku do mojego starego. – JAB