PPy3/NumPy: Różnice pomiędzy wersjami
(Utworzono nową stronę "=NumPy: rachunki numeryczne na tablicach liczb= left == Pakiet Numpy == Moduł [http://numpy.scipy.org/ Numpy] jest podstawowym zestawem nar...") |
|||
Linia 11: | Linia 11: | ||
Najważniejszym obiektem, na którym bazuje pakiet Numpy i szereg pakietów z niego korzystających jest klasa <tt>ndarray</tt> wprowadzająca obiekty <tt>array</tt>. Obiekty <tt>array</tt> możemy traktować jako uniwersalne pojemniki na dane w postaci ''macierzy'' (czyli ''wektorów'' lub ''tablic''). W porównaniu ze standardowymi typami sekwencji Pythonowych (lista, krotka) jest kilka różnic w operowaniu tymi obiektami: | Najważniejszym obiektem, na którym bazuje pakiet Numpy i szereg pakietów z niego korzystających jest klasa <tt>ndarray</tt> wprowadzająca obiekty <tt>array</tt>. Obiekty <tt>array</tt> możemy traktować jako uniwersalne pojemniki na dane w postaci ''macierzy'' (czyli ''wektorów'' lub ''tablic''). W porównaniu ze standardowymi typami sekwencji Pythonowych (lista, krotka) jest kilka różnic w operowaniu tymi obiektami: | ||
− | # obiekty przechowywane w | + | # obiekty przechowywane w tablicy <tt>array</tt> muszą być wszystkie tego samego typu; |
# obiekty <tt>array</tt> zachowują swój rozmiar; przy zmianie rozmiaru takiego obiektu powstaje nowy obiekt, a obiekt sprzed zmiany zostaje usunięty; | # obiekty <tt>array</tt> zachowują swój rozmiar; przy zmianie rozmiaru takiego obiektu powstaje nowy obiekt, a obiekt sprzed zmiany zostaje usunięty; | ||
# obiekty <tt>array</tt> wyposażone są w bogaty zestaw funkcji operujących na wszystkich przechowywanych w obiekcie danych, specjalnie optymalizowanych do przetwarzania dużych ilości danych. Jak to działa zostanie zaprezentowane poniżej. | # obiekty <tt>array</tt> wyposażone są w bogaty zestaw funkcji operujących na wszystkich przechowywanych w obiekcie danych, specjalnie optymalizowanych do przetwarzania dużych ilości danych. Jak to działa zostanie zaprezentowane poniżej. | ||
+ | |||
+ | ==Tworzenie tablic== | ||
+ | |||
+ | Najprostszym sposobem stworzenia tablicy Numpy jest wywołanie funkcji <tt>array</tt> z argumentem w postaci listy liczb. Jeśli zamiast listy liczb użyjemy listy zawierającej inne listy (tzw. listy ''zagnieżdżone''), to otrzymamy tablicę wielowymiarową. Na przykład jeśli listy są podwójnie zagnieżdzone, to otrzymujemy tablicę dwuwymiarową (macierz). | ||
+ | |||
+ | <source lang=python> | ||
+ | # przykład wykorzystania Numpy | ||
+ | >>> import numpy | ||
+ | >>> A = numpy.array([1, 3, 7, 2, 8]) | ||
+ | array([1, 3, 7, 2, 8]) | ||
+ | >>> B = numpy.array([[1, 2, 3], [4, 5, 6]]) | ||
+ | >>> B | ||
+ | array([[1, 2, 3], | ||
+ | [4, 5, 6]]) | ||
+ | >>> B.transpose() | ||
+ | array([[1, 4], | ||
+ | [2, 5], | ||
+ | [3, 6]]) | ||
+ | </source> | ||
+ | |||
+ | Innym sposobem tworzenia tablicy jest funkcja <tt>numpy.arange</tt>, która działa analogicznie do <tt>range</tt>, tyle tylko, że zwraca tablicę NumPy zamiast listy, i dopuszcza parametry ułamkowe -- a nie tylko całkowite. | ||
+ | |||
+ | Argumenty są takie same: | ||
+ | |||
+ | # indeks początkowy [opcjonalnie, domyślnie 0] | ||
+ | # indeks następny po końcowym | ||
+ | # krok [opcjonalnie, domyślnie 1] | ||
+ | |||
+ | <source lang= python> | ||
+ | >>> numpy.arange(1000000) | ||
+ | array([ 0, 1, 2, ..., 999997, 999998, 999999]) | ||
+ | >>> numpy.arange(0.1, 0.2, 0.01) | ||
+ | array([ 0.1 , 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19]) | ||
+ | >>> numpy.arange(0.9, 0.0, -0.1) | ||
+ | array([ 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1]) | ||
+ | </source> | ||
+ | |||
+ | Jak było już wspomniane, w przypadku tablicy <tt>array</tt> typowe operacje matematyczne możemy przeprowadzić dla wszystkich elementów tablicy przy użyciu jednego operatora lub funkcji. Zachowanie takie jest odmienne niż w przypadku list czy innych sekwencji Pythona. Jeśli chcielibyśmy na przykład pomnożyć wszystkie elementy listy <tt>L</tt> przez liczbę <tt>a</tt>, musimy użyć pętli: | ||
+ | |||
+ | <source lang=python> | ||
+ | L = [1, 3, 5, 2, 3, 1] | ||
+ | for k, x in enumerate(L): | ||
+ | L[k] = a * x | ||
+ | </source> | ||
+ | |||
+ | Można też zapisać to zwięźlej, używając wyrażenia generatorowego: | ||
+ | |||
+ | <source lang=python> | ||
+ | L = [1, 3, 5, 2, 3, 1] | ||
+ | L = [a * x for x in L] | ||
+ | </source> | ||
+ | |||
+ | jest to jednak poniekąd tylko uproszczony zapis pętli. Natomiast mnożenie wszystkich elementów tablicy <tt>M</tt> przez liczbę <tt>a</tt> wygląda tak: | ||
+ | |||
+ | <source lang= python> | ||
+ | M = numpy.array([1, 3, 5, 2, 3, 1]) | ||
+ | M = a * M | ||
+ | </source> | ||
+ | |||
+ | Operacje wykonywane od razu na całych macierzach mają wiele zalet. Kod programu jest prostszy i krótszy, przez co mniej podatny na błędy. Poza tym nie musimy przejmować się konkretną realizacją danej operacji — robi to za nas funkcja pakietu Numpy, która jest specjalnie optymalizowana, żeby działała jak najszybciej. | ||
+ | |||
+ | ;Inne: zob.[http://docs.scipy.org/doc/numpy/reference/generated/numpy.mgrid.html numpy.mgrid], [http://docs.scipy.org/doc/numpy/reference/generated/numpy.ogrid.html numpy.ogrid], [http://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html numpy.linspace], [http://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html numpy.zeros], [http://docs.scipy.org/doc/numpy/reference/generated/numpy.ones.html numpy.ones], [http://docs.scipy.org/doc/numpy/reference/generated/numpy.r_.html numpy.r_]. | ||
+ | |||
+ | |||
+ | =Ćwiczenia= | ||
+ | |||
+ | 1. Napisz funkcję <tt>zastap_zera(A, x)</tt>, która zwraca tablicę utworzoną z tablicy <tt>A</tt> | ||
+ | (o dowolnym kształcie) poprzez zastąpienie wszystkich elementów równych zero | ||
+ | liczbą <tt>x</tt>. Sama tablica <tt>A</tt> powinna pozostać niezmieniona. | ||
+ | |||
+ | 2. Napisz funkcję, która w minimalnej liczbie kroków tworzy (i zwraca) | ||
+ | kwadratową tablicę NumPy zawierającą na przemian jedynki i zera, o | ||
+ | dowolnym - zadanym przez argument wywołania - rozmiarze, w postaci: | ||
+ | <source lang=python> | ||
+ | In [1]: from naprzemian import naprzemian | ||
+ | |||
+ | In [2]: naprzemian(2) | ||
+ | Out[2]: | ||
+ | array([[ 1., 0.], | ||
+ | [ 0., 1.]]) | ||
+ | |||
+ | In [3]: naprzemian(3) | ||
+ | Out[3]: | ||
+ | array([[ 1., 0., 1.], | ||
+ | [ 0., 1., 0.], | ||
+ | [ 1., 0., 1.]]) | ||
+ | |||
+ | In [4]: naprzemian(4) | ||
+ | Out[4]: | ||
+ | array([[ 1., 0., 1., 0.], | ||
+ | [ 0., 1., 0., 1.], | ||
+ | [ 1., 0., 1., 0.], | ||
+ | [ 0., 1., 0., 1.]]) | ||
+ | |||
+ | In [5]: naprzemian(5) | ||
+ | Out[5]: | ||
+ | array([[ 1., 0., 1., 0., 1.], | ||
+ | [ 0., 1., 0., 1., 0.], | ||
+ | [ 1., 0., 1., 0., 1.], | ||
+ | [ 0., 1., 0., 1., 0.], | ||
+ | [ 1., 0., 1., 0., 1.]]) | ||
+ | </source> | ||
Wersja z 15:23, 8 gru 2016
Spis treści
NumPy: rachunki numeryczne na tablicach liczb
Pakiet Numpy
Moduł Numpy jest podstawowym zestawem narzędzi dla języka Python umożliwiającym zaawansowane obliczenia matematyczne, w szczególności do zastosowań naukowych (tzw. obliczenia numeryczne, jak mnożenie i dodawanie macierzy, diagonalizacja czy odwrócenie, całkowanie, rozwiązywanie równań, itd.). Daje on nam do dyspozycji specjalizowane typy danych, operacje i funkcje, których nie ma w typowej instalacji Pythona. Natomiast moduł Scipy pozwala na dostęp do bardziej złożonych i różnorodnych algorytmów wykorzystujących narzędzia dostarczone w Numpy.
Przedstawimy tutaj tylko wstęp do Numpy. Wynika to z faktu, że opisanie licznych funkcji dostępnych w bibliotece Numpy jest ogromną pracą, która zupełnie nie ma sensu — równie dobrze można zajrzeć bezpośrednio do źródła, http://docs.scipy.org/doc/numpy/reference/.
Najważniejszym obiektem, na którym bazuje pakiet Numpy i szereg pakietów z niego korzystających jest klasa ndarray wprowadzająca obiekty array. Obiekty array możemy traktować jako uniwersalne pojemniki na dane w postaci macierzy (czyli wektorów lub tablic). W porównaniu ze standardowymi typami sekwencji Pythonowych (lista, krotka) jest kilka różnic w operowaniu tymi obiektami:
- obiekty przechowywane w tablicy array muszą być wszystkie tego samego typu;
- obiekty array zachowują swój rozmiar; przy zmianie rozmiaru takiego obiektu powstaje nowy obiekt, a obiekt sprzed zmiany zostaje usunięty;
- obiekty array wyposażone są w bogaty zestaw funkcji operujących na wszystkich przechowywanych w obiekcie danych, specjalnie optymalizowanych do przetwarzania dużych ilości danych. Jak to działa zostanie zaprezentowane poniżej.
Tworzenie tablic
Najprostszym sposobem stworzenia tablicy Numpy jest wywołanie funkcji array z argumentem w postaci listy liczb. Jeśli zamiast listy liczb użyjemy listy zawierającej inne listy (tzw. listy zagnieżdżone), to otrzymamy tablicę wielowymiarową. Na przykład jeśli listy są podwójnie zagnieżdzone, to otrzymujemy tablicę dwuwymiarową (macierz).
# przykład wykorzystania Numpy
>>> import numpy
>>> A = numpy.array([1, 3, 7, 2, 8])
array([1, 3, 7, 2, 8])
>>> B = numpy.array([[1, 2, 3], [4, 5, 6]])
>>> B
array([[1, 2, 3],
[4, 5, 6]])
>>> B.transpose()
array([[1, 4],
[2, 5],
[3, 6]])
Innym sposobem tworzenia tablicy jest funkcja numpy.arange, która działa analogicznie do range, tyle tylko, że zwraca tablicę NumPy zamiast listy, i dopuszcza parametry ułamkowe -- a nie tylko całkowite.
Argumenty są takie same:
- indeks początkowy [opcjonalnie, domyślnie 0]
- indeks następny po końcowym
- krok [opcjonalnie, domyślnie 1]
>>> numpy.arange(1000000)
array([ 0, 1, 2, ..., 999997, 999998, 999999])
>>> numpy.arange(0.1, 0.2, 0.01)
array([ 0.1 , 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19])
>>> numpy.arange(0.9, 0.0, -0.1)
array([ 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1])
Jak było już wspomniane, w przypadku tablicy array typowe operacje matematyczne możemy przeprowadzić dla wszystkich elementów tablicy przy użyciu jednego operatora lub funkcji. Zachowanie takie jest odmienne niż w przypadku list czy innych sekwencji Pythona. Jeśli chcielibyśmy na przykład pomnożyć wszystkie elementy listy L przez liczbę a, musimy użyć pętli:
L = [1, 3, 5, 2, 3, 1]
for k, x in enumerate(L):
L[k] = a * x
Można też zapisać to zwięźlej, używając wyrażenia generatorowego:
L = [1, 3, 5, 2, 3, 1]
L = [a * x for x in L]
jest to jednak poniekąd tylko uproszczony zapis pętli. Natomiast mnożenie wszystkich elementów tablicy M przez liczbę a wygląda tak:
M = numpy.array([1, 3, 5, 2, 3, 1])
M = a * M
Operacje wykonywane od razu na całych macierzach mają wiele zalet. Kod programu jest prostszy i krótszy, przez co mniej podatny na błędy. Poza tym nie musimy przejmować się konkretną realizacją danej operacji — robi to za nas funkcja pakietu Numpy, która jest specjalnie optymalizowana, żeby działała jak najszybciej.
- Inne
- zob.numpy.mgrid, numpy.ogrid, numpy.linspace, numpy.zeros, numpy.ones, numpy.r_.
Ćwiczenia
1. Napisz funkcję zastap_zera(A, x), która zwraca tablicę utworzoną z tablicy A (o dowolnym kształcie) poprzez zastąpienie wszystkich elementów równych zero liczbą x. Sama tablica A powinna pozostać niezmieniona.
2. Napisz funkcję, która w minimalnej liczbie kroków tworzy (i zwraca) kwadratową tablicę NumPy zawierającą na przemian jedynki i zera, o dowolnym - zadanym przez argument wywołania - rozmiarze, w postaci:
In [1]: from naprzemian import naprzemian
In [2]: naprzemian(2)
Out[2]:
array([[ 1., 0.],
[ 0., 1.]])
In [3]: naprzemian(3)
Out[3]:
array([[ 1., 0., 1.],
[ 0., 1., 0.],
[ 1., 0., 1.]])
In [4]: naprzemian(4)
Out[4]:
array([[ 1., 0., 1., 0.],
[ 0., 1., 0., 1.],
[ 1., 0., 1., 0.],
[ 0., 1., 0., 1.]])
In [5]: naprzemian(5)
Out[5]:
array([[ 1., 0., 1., 0., 1.],
[ 0., 1., 0., 1., 0.],
[ 1., 0., 1., 0., 1.],
[ 0., 1., 0., 1., 0.],
[ 1., 0., 1., 0., 1.]])