2. Matplotlib

Jedną z potężniejszych bibliotek Pythona jest matplotlib, która służy do tworzenia różnego rodzaju wykresów. W tym scenariuszu pokażemy, jak przygotować wykresy funkcji w dwuwymiarowym układzie współrzędnych.

2.1. Środowisko pracy

Informacja

Do kodowania i uruchamiania skryptu możesz użyć dowolnych narzędzi, np. ulubionego edytora kodu i terminala. Sugerujemy jednak wykorzystanie środowiska typu PyCharm lub innego, ponieważ ułatwiają przygotowania i pracę nad projektami w języku Python.

Przed rozpoczęciem pracy przygotuj w wybranym katalogu, np. matplot wirtualne środowisko Pythona i w aktywnym środowisku zainstaluj pakiet Matplotlib:

(.venv) ~/matplot$ pip install matplotlib

Informacja

Matplotlib oferuje dwa główne style kodowania:

  • styl jawny, zorientowany obiektowo, w którym po kolei tworzymy wszystkie elementy budujące wykres, takie jak Figure, Axes czy Axis,

  • styl niejawny, w którym korzystamy z funkcji interfejsu pyplot.

Oficjalna dokumentacja sugeruje, aby w bardziej złożonych projektach stosować styl jawny. Tak zrobimy w przykładach korzystających z funkcji matematycznych, które zaczynać będziemy następującymi importami:

import matplotlib.pyplot as plt
import numpy as np

W pierwszym wierszu importujemy interfejs pyplot pod skróconą nazwą (aliasem) plt. W drugim importujemy towarzyszącą modułowi matplotlib bibliotekę numpy pod aliasem np. Dostarcza ona wielu narzędzi wspomagających obliczenia naukowe.

2.2. Anatomia wykresu

Zacznijmy od prostego przykładu, który możemy przetestować w konsoli Pythona:

Terminal. Kod nr
import matplotlib.pyplot as plt
x = [1, 2, 3]
y = [4, 6, 5]
plt.plot(x, y)
plt.show()

Tworzenie wykresów punktowych jest proste. Postępujemy według schematu:

  • przygotowujemy dwie listy wartości: argumentów x i wartości y, odpowiadające sobie wartości zinterpretowane zostaną jako współrzędne punktów w 2-wymiarowym układzie współrzędnych,

  • obie listy przekazujemy jako argumenty metody plot(),

  • wyświetlamy wykres za pomocą metody show().

W powyższym przykładzie zastosowaliśmy niejawny styl kodowania wystarczający do prostych pojedynczych wykresów. W jawnym stylu kodowania dwie ostatnie linie zastąpimy poniższym kodem:

fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()

Żeby lepiej go rozumieć, musimy poznać składniki wykresu. Twórcy pakietu przyjęli następującą terminologię:

  • Figure – nadrzędny pojemnik zawierający wszystkie inne składniki, w praktyce będzie to okno zawierające wykres(y),

  • Axes – obiekt reprezentujący pojedynczy wykres i jego elementy, wykresów w figurze może być wiele.

Najprostszym sposobem stworzenia omówionych obiektów jest użycie metody subplots(): fig, ax = plt.subplots().

Figura (Figure) zawiera wykres(y). Wykres (Axes) może z kolei zawierać różne elementy pokazane na poniższym diagramie:

../_images/anatomy.webp
  • Title – tytuł ustawiany za pomocą: plt.title() lub ax.set_title(),

  • Legend – legenda wykresu może być dodana za pomocą plt.legend() lub ax.legend(),

  • Axis – obiekty reprezentujące osie X, Y (2D) i ewentualnie Z (3D), zawierają:

    • skalę osi (ang. tick) – znaczniki skali, główne (ang. major) i poboczne (ang. minor),

    • etykiety osi (ang. label) – możemy je ustawić za pomocą plt.xlabel() lub metod wykresu: ax.set_xlabel(), ax.set_ylabel(),

  • Markers – pojedyncze punkty, które można dodać za pomocą ax.scatter(),

  • Line – linie generowane przez metodę plot(),

  • Grid – siatka wykresu, którą można dodać za pomoca metody grid().

2.3. Funkcja liniowa

Zadania: Wykonaj wykres funkcji f(x) = a*x + b.

Dane:

  • współczynnik kierunkowy a i wyraz wolny b, liczby całkowite,

  • lista argumentów x zawierająca liczby całkowite z zakresu <-10;10>.

W pliku matplot01.py umieszczamy poniższy kod:

Kod nr
 1import matplotlib.pyplot as plt
 2
 3a = 1
 4b = 2
 5
 6x = range(-10, 11)  # lista argumentów x
 7y = []  # lista wartości
 8for i in x:
 9    y.append(a * i + b)
10
11fig, ax = plt.subplots()
12ax.plot(x, y)
13ax.set_title('Wykres f(x) = a*x - b')
14ax.grid(True)
15plt.show()

Na początku nadajemy wartości parametrom a i b. Następnie postępujemy wg omówionego schematu. Generujemy listę argumentów x za pomocą funkcji range(). W pętli for dla każdego argumentu obliczamy wartość funkcji i dodajemy do listy y.

Następnie stosujemy jawny styl kodowania, tzn. używamy metody subplots(), która obiekty reprezentujące figurę (fig, okno) i wykres (ax). Serie danych dodajemy za pomocą metody plot(), która wizualizuje je domyślnie przy użyciu linii ciągłych. Dodajemy tytuł (set_title()) i siatkę (ax.grid()). Na koniec wyświetlamy wykres (plt.show()).

2.3.1. Ćwiczenie 1

Zmodyfikuj powyższy kod tak, aby współczynniki a i b oraz zakres argumentów x pobierane były z klawiatury. Sprawdź poprawność działania programu.

2.3.2. Ćwiczenie 2

W konsoli Pythona wydajemy następujące polecenia:

Terminal. Kod nr
>>> a = 2
>>> x = range(11)
>>> for i in x:
...   print(a + i)
>>> y = [a + i for i in x]
>>> print(y)

Powyższy przykład wykorzystuje tzw. wyrażenie listowe, które zwięźle zastępuje pętlę i zwraca listę wartości. Jego działanie należy rozumieć następująco: dla każdej wartości i (nazwa zmiennej dowolna) odczytywanej w pętli z listy x (for i in x) wylicz wyrażenie a + i i umieść w liście y.

Użyjmy wyrażenia listowego w naszym programie:

Kod nr
 1import matplotlib.pyplot as plt
 2
 3a = int(input('Podaj współczynnik a: '))
 4b = int(input('Podaj współczynnik b: '))
 5x_min = int(input('Podaj wartość minimalną x: '))
 6x_max = int(input('Podaj wartość maksymalną x: '))
 7
 8x = range(x_min, x_max+1)  # lista argumentów x
 9# wyrażenie listowe wylicza zbiór wartości y
10y = [a * i + b for i in x]
11
12fig, ax = plt.subplots()
13ax.plot(x, y)
14ax.set_title('Wykres f(x) = a*x - b')
15ax.grid(True)
16plt.show()

2.4. Dwie funkcje

Zadanie: wykonaj wykres podanych funkcji:

  • f(x) = x/(-3) + a dla x <= 0,

  • f(x) = x*x/3 dla x >= 0,

– gdzie x = <-10;10> z krokiem 0.5.

Dane:

  • współczynnik a pobrany z klawiatury, liczba całkowita.

  • lista argumentów x zawierająca liczby z zakresu <-10;10> z krokiem 0.5.

Wykonanie zadania wymaga na początku wygenerowania listy argumentów. Do tego celu możemy wykorzystać funkcję arange(). Listę wartości funkcji wyliczymy za pomocą wyrażenia listowego.

2.4.1. Ćwiczenie 3

Zanim zrealizujemy zadanie przećwiczmy w konsoli Pythona następujący kod:

Terminal. Kod nr
>>> import numpy as np
>>> x = np.arange(-10, 10.5, 0.5)
>>> print(x)
>>> len(x)
>>> a = 3
>>> y1 = [i / -3 + a for i in x if i <= 0]
>>> len(y1)

Funkcja arange() znajduje się w module numpy i zwraca listę wartości zmiennoprzecinkowych (zob. typy danych) z zakresu określonego przez dwa pierwsze argumenty i z krokiem wyznaczonym przez argument trzeci.

Do obliczenia wartości pierwszej funkcji x / -3 wykorzystujemy wyrażenie listowe uzupełnione o instrukcję warunkową if i <= 0, która ogranicza zbiór argumentów, dla których obliczana jest wartość funkcji.

Ostrzeżenie

Nie zamykaj tej sesji konsoli, będziemy z niej korzystać w kolejnych ćwiczeniach.

W pliku matplot03.py umieszczamy poniższy kod:

Kod nr
 1import matplotlib.pyplot as plt
 2import numpy as np
 3
 4x = np.arange(-10, 10.5, 0.5)  # lista argumentów x
 5a = int(input("Podaj współczynnik a: "))
 6y1 = [i / -3 + a for i in x if i <= 0]
 7
 8fig, ax = plt.subplots()
 9ax.plot(x, y1)
10ax.set_title('Wykres f(x)')
11ax.grid(True)
12plt.show()

Uruchom program. Nie działa, dostajemy komunikat: ValueError: x and y must have same first dimension, but have shapes (41,) and (21,), który oznacza, że listy x i y1 powinny mieć tyle samo elementów, ale nie mają. Przyczyną tego jest fakt, że w powyższym kodzie wyliczyliśmy 21 wartości funkcji (dla argumentów mniejszych lub równych zero), a wszystkich argumentów jest 41.

Błąd można usunąć poprzez zawężenie listy argumentów do 21 elementów.

2.4.2. Ćwiczenie 4

Wróćmy do konsoli Pythona z wprowadzonym i wykonanym wcześniejszym kodem. Wpisujemy podane niżej polecenia:

Terminal. Kod nr
>>> x
>>> x[0]
>>> x[0:22]
>>> x[:22]
>>> x[:len(y1)]
>>> len(x[:len(y1)])

Podane wyżej przykłady ilustrują działanie notacji wycinkowej (zob.: notacja wycinkowa), której obecność rozpoznajemy po znaku dwukropka. Pozwala ona odczytywać z listy tylko wskazany przez indeksy zakres elementów. W naszym przypadku wszystkie podane przykłady, tzn. 0:22, :22, :len(y1) – wskazują pierwsze 21 elementów listy. Jeżeli brak indeksu początkowego przed dwukropkiem, domyślną wartością jest 0 (zero), indeks po dwukropku oznacza z kolei element końcowy, przy czym nie wchodzi on do odczytywanego zakresu.

Zmieniamy więc wywołanie funkcji plot() w naszym skrypcie:

Kod nr
ax.plot(x[:len(y1)], y1)

Uruchom i przetestuj działanie programu.

2.4.3. Ćwiczenie 5

Udało się nam zrealizować pierwszą część zadania, tzn. uzyskać wykres jednej funkcji. Aby uzyskać wykres drugiej funkcji, musimy uzupełnić skrypt o instrukcję obliczającą wartości dla drugiej funkcji. Umieszczamy więc we właściwym miejscu poniższy kod:

Kod nr
y2 = [i**2 / 3 for i in x if i >= 0]

Zanim dokończymy zadanie, wróćmy jeszcze raz do konsoli Pythona z wprowadzonym i wykonanym wcześniejszym kodem. Wpisujemy podane niżej polecenia:

Terminal. Kod nr
>>> len(x)
>>> x[-10]
>>> x[-10:]
>>> len(y2)
>>> x[-len(y2):]

W notacji wycinkowej (zob.: notacja wycinkowa) możemy używać również indeksów ujemnych wskazujących elementy od końca listy. Jeżeli taki indeks umieścimy jako pierwszy przed dwukropkiem, czyli separatorem przedziału, dostaniemy resztę elementów listy.

Metoda plot() może otrzymać kilka zestawów argumentów x i wartości y. Wykorzystamy tę możliwość oraz notację indeksową do narysowania wykresu drugiej funkcji. W skrypcie modyfikujemy instrukcję plot():

Kod nr
ax.plot(x[:len(y1)], y1, x[-len(y2):], y2)

2.4.4. Ćwiczenie 6

Spróbuj dziedziny wartości x dla funkcji y1 i y2 wyznaczyć nie za pomocą notacji wycinkowej, ale przy użyciu wyrażeń listowych, których wynik przypisz do zmiennych x1 i x2. Użyj ich jako argumentów funkcji plot() i przetestuj program.

Wykres dwóch funkcji:

../_images/dwiefunkcje.png

2.5. Ruchy Browna

Napiszemy program, który symuluje ruchy Browna. Jak wiadomo są to chaotyczne ruchy cząsteczek, które będziemy mogli zwizualizować w płaszczyźnie dwuwymiarowej. Na początku przyjmujemy następujące założenia:

  • cząsteczka, której ruch będziemy śledzić, znajduje się w początku układu współrzędnych (0, 0);

  • w każdym ruchu cząsteczka przemieszcza się o stały wektor o wartości 1;

  • kierunek ruchu wyznaczać będziemy losując kąt z zakresu <0; 2Pi>;

  • współrzędne kolejnego położenia cząsteczki wyliczać będziemy ze wzorów:

    x_n = x_{n-1} + r * cos(\phi)

y_n = y_{n-1} + r * sin(\phi)

    – gdzie: r – długość jednego kroku, \phi – kąt wskazujący kierunek ruchu w odniesieniu do osi 0X.

  • końcowy wektor przesunięcia obliczymy ze wzoru: |s| = \sqrt{(x^2 + y^2)}

Zacznijmy od wyliczenia współrzędnych opisujących ruch cząsteczki. Do pustego pliku o nazwie rbrowna.py wpisujemy:

Plik rbrowna.py Kod nr
 1import numpy as np
 2import random
 3import matplotlib.pyplot as plt
 4
 5n = int(input('Ile ruchów? '))
 6x = y = 0
 7
 8for i in range(0, n):
 9    # wylosuj kąt i zamień go na radiany
10    rad = random.randint(0, 360) * np.pi / 180
11    x = x + np.cos(rad)  # wylicz współrzędną x
12    y = y + np.sin(rad)  # wylicz współrzędną y
13    print(f'x = {x:.2f}, y = {y:.2f}')

Funkcje trygonometryczne zawarte w module np wymagają kąta podanego w radianach, dlatego wylosowany kąt mnożymy przez wyrażenie np.pi / 180. Obliczone współrzędne kolejnych punktów wypisujemy przy użyciu wyjścia formatowanego. Przykładowy zapis {x:.2f} wypisuje zmienną x jako liczbę zmiennoprzecinkową z dokładnością do 2 miejsc po przecinku.

2.5.1. Ćwiczenie 6

Wyliczane współrzędne x i y należy zapisywać do osobnych list. Wstaw wiec w odpowiednich miejscach pliku poniższe instrukcje:

Kod nr
lx = [0]
ly = [0]

lx.append(x)
ly.append(y)

Na końcu skryptu umieść instrukcje wyliczającą końcowy wektor przesunięcia oraz wypisującą obliczoną wartość:

Kod nr
s = np.fabs(np.sqrt(x**2 + y**2))
print('Wektor przesunięcia: {s:.2f}')

Przetestuj program. Przykładowy wynik działania to komunikaty wypisane w terminalu:

x = -4.86, y = -3.51
x = -3.86, y = -3.59
x = -3.84, y = -4.59
x = -4.13, y = -5.55
Wektor przesunięcia: 6.92

Pozostaje dopisanie instrukcji generujących wykres. Poniższy kod pokazuje również użycie metod wzbogacających wykres o legendę, etykiety osi i tytuł.

Kod nr
 1import numpy as np
 2import random
 3import matplotlib.pyplot as plt
 4
 5n = int(input('Ile ruchów? '))
 6x = y = 0
 7lx = [0]
 8ly = [0]
 9
10for i in range(0, n):
11    # wylosuj kąt i zamień go na radiany
12    rad = random.randint(0, 360) * np.pi / 180
13    x = x + np.cos(rad)  # wylicz współrzędną x
14    y = y + np.sin(rad)  # wylicz współrzędną y
15    print(f'x = {x:.2f}, y = {y:.2f}')
16    lx.append(x)
17    ly.append(y)
18
19# oblicz i wypisz wektor końcowego przesunięcia
20s = np.fabs(np.sqrt(x ** 2 + y ** 2))
21print(f'Wektor przesunięcia: {s:.2f}')
22
23fig, ax = plt.subplots()
24ax.plot(lx, ly, 'o:g', linewidth=2, alpha=0.5)
25ax.legend([f'Dane x, y\nPrzemieszczenie: {s:.2f}'], loc='upper left')
26ax.set_xlabel('lx')
27ax.set_ylabel('ly')
28ax.set_title('Ruchy Browna')
29ax.grid(True)
30plt.show()

Przeanalizujmy dodatkowe parametry formatujące wykres w poleceniu ax.plot(lx, ly, 'o:g', linewidth=2, alpha=0.5):

  • 'o:' – ciąg formatujący składający się z 3 opcjonalnych znaków wg schematu '[marker][linia][kolor]', np. marker o określa znak użyty do rysowania punktów (kółko), następny znak : określa styl rysowania linii (kropki), trzeci znak g ustawia kolor (zielony) (zob. sekcję w dokumentacji: Format Strings),

  • color='green' – kolor wykresu można podać w osobnym parametrze,

  • linewidth=2 – parametr pozwala ustawić grubość linii,

  • alpha=0.5 – określa przezroczystość.

Poeksperymentuj z innymi ciągami formatującymi, np: r:., r:+, r., r+.

2.5.2. Ćwiczenie 7

Spróbuj dodać do wykresu prostą linią w kolorze niebieskim oznaczającą wektor przesunięcia.

Wskazówka

Użyj drugiego wywołania metody plot() z argumentami zawierającymi współrzędne punktu początkowego i końcowego ruchu cząsteczki.

Przykładowy wykres:

../_images/rbrowna.png

2.6. Zadania dodatkowe

  1. Przygotuj wykres funkcji kwadratowej: f(x) = a*x^2 + b*x + c, gdzie x = <-10;10> z krokiem 1, przyjmij następujące wartości współczynników: a = 1, b = -3, c = 1.

Uzyskany wykres powinien wyglądać następująco:

../_images/fkwadratowa.png

Licencja Creative Commons Materiały Python 101 udostępniane przez Centrum Edukacji Obywatelskiej na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.

Utworzony:

2026-05-30 o 19:12 w Sphinx 7.3.7

Autorzy:

Robert Bednarz