2011-11-10 14 views
35

Używam Numpy do przechowywania danych w macierzach. Pochodzący z tła R, istnieje niezwykle prosty sposób na zastosowanie funkcji nad wierszem/kolumnami lub obu macierzy.Aplikacja funkcji za pomocą wiersza/kolumny macierzy numpy

Czy jest coś podobnego w kombinacji Pythona/Numpy? Pisanie własnych implementacji nie jest problemem, ale wydaje mi się, że większość wersji, które wymyślę, będzie znacznie mniej wydajna/intensywniejsza niż jakakolwiek dotychczasowa implementacja.

Chciałbym uniknąć kopiowania z macierzy numpy do zmiennej lokalnej itp., Czy to możliwe?

Funkcje, które próbuję wprowadzić, to głównie proste porównania (np. Ile elementów pewnej kolumny jest mniejszych niż liczba x lub ile z nich ma wartość bezwzględną większą niż y).

+2

Umieść przykładowy kod z żądanymi danymi wyjściowymi. Z twojego polecenia na odpowiedź unutbu, wygląda na to, że to, czego chcesz, jest bardzo proste, ale na razie jest zbyt abstrakcyjne, aby ktokolwiek mógł ci udzielić użytecznych porad. – heltonbiker

Odpowiedz

43

Prawie wszystkie funkcje numpy działają na całych tablicach i/lub można je opowiadać o działaniu na określonej osi (wiersz lub kolumna).

Dopóki można zdefiniować swoją funkcję w postaci funkcji numpy działających na numpy array lub plasterkach macierzy, funkcja będzie automatycznie działać na całych tablicach, wierszach lub kolumnach.

Pomocne może być zapytanie o to, jak wdrożyć określoną funkcję, aby uzyskać bardziej konkretne porady.


Numpy zapewnia np.vectorize i np.frompyfunc aby włączyć funkcje Pythona, które operują na liczbach do funkcji, które działają na NumPy tablic.

Na przykład

def myfunc(a,b): 
    if (a>b): return a 
    else: return b 
vecfunc = np.vectorize(myfunc) 
result=vecfunc([[1,2,3],[5,6,9]],[7,4,5]) 
print(result) 
# [[7 4 5] 
# [7 6 9]] 

(Elementy pierwszego układu zastępowane przez odpowiedni element drugiej tablicy, gdy drugi jest większy).

Ale nie zbyt podniecony; np.vectorize i np.frompyfuncjust syntactic sugar. W rzeczywistości nie powodują, że twój kod jest szybszy. Jeśli podstawowa funkcja Pythona działa na jednej wartości na raz, to np.vectorize będzie ją podawać po jednym elemencie naraz, a cała operacja będzie dość powolna (w porównaniu do użycia funkcji numpy, która wywołuje pewne ukryte C lub Fortran realizacja).


policzyć ile elementy kolumny x są mniejsze niż liczba y, można użyć wyrażenia takie jak:

(array['x']<y).sum() 

Na przykład:

import numpy as np 
array=np.arange(6).view([('x',np.int),('y',np.int)]) 
print(array) 
# [(0, 1) (2, 3) (4, 5)] 

print(array['x']) 
# [0 2 4] 

print(array['x']<3) 
# [ True True False] 

print((array['x']<3).sum()) 
# 2 
+0

Więc nie ma prostego sposobu na uruchomienie funkcji ogólnej? (ciekawe, ogólnie rzecz biorąc, funkcje numpy powinny wystarczyć - wystarczy wykonać proste porównania, np. ile elementów kolumny x jest mniejszych niż liczba y) – petr

+0

Brzmi to tak, jakbyś mógł robić tego rodzaju rzeczy z plasterkami. – wim

+0

Dziękuję bardzo! .. więc jeśli zrobię tablicę ['x'] <3, jest to obsługiwane przez szybszą implementację numpy w porównaniu do mojej własnej funkcji wektorowej? – petr

14

wybierania elementów z Tablica NumPy oparta na jednym lub kilku warunkach jest prosta, używając pięknie gęstej składni NumPy:

>>> import numpy as NP 
>>> # generate a matrix to demo the code 
>>> A = NP.random.randint(0, 10, 40).reshape(8, 5) 
>>> A 
    array([[6, 7, 6, 4, 8], 
     [7, 3, 7, 9, 9], 
     [4, 2, 5, 9, 8], 
     [3, 8, 2, 6, 3], 
     [2, 1, 8, 0, 0], 
     [8, 3, 9, 4, 8], 
     [3, 3, 9, 8, 4], 
     [5, 4, 8, 3, 0]]) 


ile elementów w kolumnie 2 są większe niż 6?

>>> ndx = A[:,1] > 6 
>>> ndx 
     array([False, True, False, False, True, True, True, True], dtype=bool) 
>>> NP.sum(ndx) 
     5 


ile elementów w ostatniej kolumnie A mają wartość bezwzględną większą niż 3?

>>> A = NP.random.randint(-4, 4, 40).reshape(8, 5) 
>>> A 
    array([[-4, -1, 2, 0, 3], 
     [-4, -1, -1, -1, 1], 
     [-1, -2, 2, -2, 3], 
     [ 1, -4, -1, 0, 0], 
     [-4, 3, -3, 3, -1], 
     [ 3, 0, -4, -1, -3], 
     [ 3, -4, 0, -3, -2], 
     [ 3, -4, -4, -4, 1]]) 

>>> ndx = NP.abs(A[:,-1]) > 3 
>>> NP.sum(ndx) 
     0 


ile elementów w dwóch pierwszych rzędach A są większe lub równe 2?

>>> ndx = A[:2,:] >= 2 
>>> NP.sum(ndx.ravel()) # 'ravel' just flattens ndx, which is originally 2D (2x5) 
     2 

składnia indeksowanie NumPy jest dość blisko R użytkownika; biorąc pod uwagę swoją biegłość w dziedzinie badań, tutaj są najważniejsze różnice między R i NumPy w tym kontekście:

NumPy indeksy są zera, w R, indeksowanie zaczyna się od 1

NumPy (jak Python) pozwala indeksu od prawej do lewej użyciu negatywnych wskaźników - np

# to get the last column in A 
A[:, -1], 

# to get the penultimate column in A 
A[:, -2] 

# this is a big deal, because in R, the equivalent expresson is: 
A[, dim(A)[0]-2] 

NumPy wykorzystuje dwukropek ":" notacja oznaczająca "nie łączone", np. W R, do otrzymasz pierwsze trzy wiersze w A, których użyjesz, A [1: 3,]. W NumPy, ty użyłby A [0: 2:] (w NumPy, "0" nie jest to konieczne, w rzeczywistości korzystne jest, aby użyć [: 2,:]

+0

dziękuję, zauważyłem adresowanie tablicy numpy przedtem, ale zawsze dobrze jest mieć ładne podsumowanie :) – petr

6

ja również pochodzić z więcej tła R i natknąłem się na brak bardziej wszechstronnego zastosowania, które mogłoby zająć krótkie niestandardowe funkcje Widziałem fora sugerujące używanie podstawowych funkcji numpy, ponieważ wiele z nich obsługuje tablice. sposób "natywna" obsługa funkcji numpy obsługi (czasami 0 jest wierszem i 1 kolumnowym, czasem przeciwnym)

Moim osobistym rozwiązaniem dla bardziej elastycznych funkcji z apply_along_axis było połączenie ich z niejawnymi funkcjami lambda dostępnymi w python. Funkcje Lambda powinny być bardzo łatwe do zrozumienia dla R myślących, którzy używają bardziej funkcjonalnego stylu programowania, jak w R działają, sapply, lapply, itp.

Tak na przykład chciałem zastosować standaryzację zmiennych w macierzy. Tipically w R jest funkcją tego (skali), ale można też zbudować go z łatwością zastosować:

(kod R)

apply(Mat,2,function(x) (x-mean(x))/sd(x)) 

Widzisz jak ciało funkcji wewnątrz Zastosuj (x-średniej (x))/sd (x) jest bitem, którego nie możemy wpisać bezpośrednio dla pytona apply_along_axis.Z lambda jest to łatwe do wykonania dla jednego zestawu wartości, tak:

(Python)

import numpy as np 
vec=np.random.randint(1,10,10) # some random data vector of integers 

(lambda x: (x-np.mean(x))/np.std(x) )(vec) 

Następnie wszystko, czego potrzebujemy, to podłączyć to wewnątrz pytona zastosowania i przekazać tablicę zainteresowania poprzez apply_along_axis

Mat=np.random.randint(1,10,3*4).reshape((3,4)) # some random data vector 
np.apply_along_axis(lambda x: (x-np.mean(x))/np.std(x),0,Mat) 

Oczywiście, funkcja lambda może być realizowany jako oddzielna funkcja, ale myślę, że cała rzecz jest użycie raczej małe funkcje zawarte w wierszu, w którym mają zastosowanie pochodzą.

Mam nadzieję, że okaże się przydatny!

Powiązane problemy