Menu Zamknij

Web scraping i MySQL część 11 – Pandas

Użycie metod, które już poznałeś do stworzenia jednej dużej tabeli może okazać się sporym wyzwaniem. Zapisanie samych nagłówków jest proste, ale trafienie z treścią w odpowiednie miejsca list już nie. Szczególnie, że dla różnych odmian nie wszystkie tabele są dostępne no i jak wiemy mają różną liczbę wierszy. Na szczęście mamy gotowe tabele zapisane w plikach .csv. Gdyby znaleźć jakiś ładny sposób na ich połączenie. Taki ładny sposób zapewni nam moduł Pandas, który analizę danych przenosi na zupełnie nowy poziom. My użyjemy tej biblioteki do połączenia danych z plików .csv w jeden poprawnie sformatowany, duży plik.

Pandas

Pandas nie jest standardowym modułem, i trzeba go zainstalować. Jeśli nie masz biblioteki Pandas, uruchom linię komend (klikając lupę koło znaczka Windows w lewym dolnym rogu, wpisując cmd i klikając enter) i wydaj polecenie pip install pandas, jeśli coś nie działa zapoznaj się z tą instrukcją.

Dataframe

Moduł Pandas wspiera typ danych nazywany Dataframe. W bardzo dużym uproszczeniu Dataframe to taki arkusz Excela: ma wiersze, kolumny i może mieć nazwy kolumn.

Na początek zaimportujmy do Dataframe tabelę „gatunek”. Popatrz na kod:

import pandas as pd

plik = "ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv"
gatunek = pd.read_csv(plik)

W 1 linijce importujemy potrzebny moduł, i nazywamy go dla ułatwienia pd. Nazwa pd jest światowym standardem, każdy tak robi i my nie mamy powodu żeby się nie dostosować.
W 3 linijce pod zmienną gatunek zapisujemy dataframe. Używamy do tego funkcji read_csv() z modułu Pandas. pd.read_csv() potrzebuje co najmniej jednego argumentu – nazwy pliku. Zobaczmy co się wydarzy po uruchomieniu programu:

==================== RESTART: F:\python38\Web scraping 11.py ===================
Traceback (most recent call last):
  File "F:\python38\Web scraping 11.py", line 5, in <module>
    gatunek = pd.read_csv(plik)
  File "F:\python38\lib\site-packages\pandas\io\parsers.py", line 676, in parser_f
    return _read(filepath_or_buffer, kwds)
  File "F:\python38\lib\site-packages\pandas\io\parsers.py", line 448, in _read
    parser = TextFileReader(fp_or_buf, **kwds)
  File "F:\python38\lib\site-packages\pandas\io\parsers.py", line 880, in __init__
    self._make_engine(self.engine)
  File "F:\python38\lib\site-packages\pandas\io\parsers.py", line 1114, in _make_engine
    self._engine = CParserWrapper(self.f, **self.options)
  File "F:\python38\lib\site-packages\pandas\io\parsers.py", line 1891, in __init__
    self._reader = parsers.TextReader(src, **kwds)
  File "pandas\_libs\parsers.pyx", line 529, in pandas._libs.parsers.TextReader.__cinit__
  File "pandas\_libs\parsers.pyx", line 749, in pandas._libs.parsers.TextReader._get_header
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x96 in position 0: invalid start byte
>>> 

No kiepsko, ale nie tragicznie. Dla nas kluczowa jest linijka UnicodeDecodeError: 'utf-8′ codec can’t decode byte 0x96 in position 0: invalid start byte. Oznacza to dwie rzeczy. Po pierwsze Pandas domyślnie używa kodowania znaków w formacie UTF-8, po drugie nie poradził sobie z jakimś znakiem w naszej tabeli. W naszym programie nie definiowaliśmy w jakim formacie mają być zapisane pliki .csv i dla Pythona nie jest oczywiste, że ma to być UTF-8.
Poinformujmy Pandas, że chcemy odczytać plik zapisany w domyślnym kodowaniu Pythona.

import pandas as pd

plik = "ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv"
gatunek = pd.read_csv(plik, engine = "python")

W 4 linijce do funkcji read_csv() dodaliśmy drugi argument – engine równy stringowi python. Zobaczmy co to zmieniło:

==================== RESTART: F:\python38\Web scraping 11.py ===================
>>> 

Nie ma błędów, dobra nasza! Pewnie jesteś niezwykle ciekawy jak taki dataframe wygląda. Obejrzyjmy go!

import pandas as pd

plik = "ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv"
gatunek = pd.read_csv(plik, engine = "python")
print(gatunek)

Kod nie jest jakoś specjalnie skomplikowany. Efekt uruchomienia go:

==================== RESTART: F:\python38\Web scraping 11.py ===================
  id_odmiany                   Gatunek – nazwa angielska    – nazwa botaniczna
0   odmiana1                 Kukurydza             Maize           Zea mays L.
1   odmiana2                 Kukurydza             Maize           Zea mays L.
2   odmiana3  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.
3   odmiana4  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.
4   odmiana5  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.
5   odmiana7                     Melon             Melon       Cucumis melo L.
6   odmiana9                     Melon             Melon       Cucumis melo L.
7  odmiana10                     Melon             Melon       Cucumis melo L.
8  odmiana11                     Melon             Melon       Cucumis melo L.
9  odmiana12                     Melon             Melon       Cucumis melo L.
>>> 

Prawda, że to taki trochę Excel? Zauważ, że kolumny są ponumerowane a numeracja zaczyna się od 0. Naszym celem jest połączenie plików w całość i w tej części kursu to jedyna rzecz do której wykorzystamy Pandas. Pamiętaj, że Pandas pomaga wykonać zaawansowaną analizę danych. Więcej zastosowań Pandas znajdziesz w moim kursie Porównaj styl pisarzy.

Spróbujmy podejrzeć sobie dwa pliki, dodajmy plik „nazwy”:

import pandas as pd

plik_gatunek = "ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv"
plik_nazwy = "ctl00_ContentPlaceHolderZawartosc_DetailsViewNazwy.csv"
gatunek = pd.read_csv(plik_gatunek, engine = "python")
nazwy = pd.read_csv(plik_nazwy, engine = "python")

print(gatunek)
print(nazwy)

I zobaczmy efekt:

  id_odmiany                   Gatunek – nazwa angielska    – nazwa botaniczna
0   odmiana1                 Kukurydza             Maize           Zea mays L.
1   odmiana2                 Kukurydza             Maize           Zea mays L.
2   odmiana3  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.
3   odmiana4  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.
4   odmiana5  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.
5   odmiana7                     Melon             Melon       Cucumis melo L.
6   odmiana9                     Melon             Melon       Cucumis melo L.
7  odmiana10                     Melon             Melon       Cucumis melo L.
8  odmiana11                     Melon             Melon       Cucumis melo L.
9  odmiana12                     Melon             Melon       Cucumis melo L.
  id_odmiany – ostateczna  ... Data opubl. nazwy Data zatw. nazwy
0   odmiana1     Aramillo  ...        15.07.2006       22.02.2007
1   odmiana2       Centos  ...        31.07.2019       13.03.2020
2   odmiana3        Belka  ...        15.11.2011       19.09.2014
3   odmiana4        Wrona  ...                         05.06.1998
4   odmiana5       Platon  ...        15.01.2012       08.03.2012
5   odmiana7         Boss  ...        30.04.2003       10.02.2005
6   odmiana9       Emirat  ...                         15.03.1996
7  odmiana10       Senior  ...        15.05.2007       16.02.2010
8  odmiana11      Materac  ...                         23.02.1998
9  odmiana12       Czarna  ...                         28.03.1990

[10 rows x 8 columns]
>>> 

Żeby połączyć pliki ze sobą, musimy mieć jakąś wspólną część w obu plikach. My przezornie taką część sobie przygotowaliśmy. W każdym z plików jest kolumna id_odmiany i ta kolumna w dodatku zawiera potrzebne nam wartości, czyli identyfikator odmiany!

merge()

Do scalenia dwóch tabeli użyjemy funkcji merge(). W funkcji merge() musimy podać 4 argumenty:
1. Nazwę 1 tabeli
2. Nazwę 2 tabeli
3. Kolumnę w której są wartości używane do porównania
4. Jak scalamy
W naszym przypadku program będzie wyglądał tak:

import pandas as pd

plik_gatunek = "ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv"
plik_nazwy = "ctl00_ContentPlaceHolderZawartosc_DetailsViewNazwy.csv"
gatunek = pd.read_csv(plik_gatunek, engine = "python")
nazwy = pd.read_csv(plik_nazwy, engine = "python")
nazwy_gatunek = pd.merge(gatunek, nazwy, on = 'id_odmiany', how = 'outer')

print(nazwy_gatunek)

W 7 linijce używamy funkcji merge() wskazując, że 1 tabela (dataframe) jest zapisana pod zmienną gatunek, 2 tabela (dataframe) jest zapisana pod zmienną nazwy, łączymy te tabele z wykorzystaniem wartości z kolumny nazwanej id_odmiany, i jest to połączenie typu outer, czyli zapisywane są wszystkie dane z 1 dataframe i wszystkie dane z 2 dataframe. Zobaczmy efekt:

===================== RESTART: F:\python38\Web scraping 11.py ====================
  id_odmiany                   Gatunek  ... Data opubl. nazwy Data zatw. nazwy
0   odmiana1                 Kukurydza  ...        15.07.2006       22.02.2007
1   odmiana2                 Kukurydza  ...        31.07.2019       13.03.2020
2   odmiana3  Pszenica zwyczajna ozima  ...        15.11.2011       19.09.2014
3   odmiana4  Pszenica zwyczajna ozima  ...                         05.06.1998
4   odmiana5  Pszenica zwyczajna ozima  ...        15.01.2012       08.03.2012
5   odmiana7                     Melon  ...        30.04.2003       10.02.2005
6   odmiana9                     Melon  ...                         15.03.1996
7  odmiana10                     Melon  ...        15.05.2007       16.02.2010
8  odmiana11                     Melon  ...                         23.02.1998
9  odmiana12                     Melon  ...                         28.03.1990

[10 rows x 11 columns]
>>> 

Z tego podglądu danych można stwierdzić jedynie, że chyba dobrze. Jak widzisz, Pandas nie chce wyświetlać zbyt dużej ilości danych, żeby nie spowalniać okna terminala. Wyświetlone zostały 2 pierwsze i 2 ostatnie kolumny. Możemy zmienić ten domyślny sposób wyświetlania i wymusić wyświetlanie wszystkich kolumn i wierszy dodając pd.options.display.width = 0.

import pandas as pd
pd.options.display.width = 0

plik_gatunek = "ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv"
plik_nazwy = "ctl00_ContentPlaceHolderZawartosc_DetailsViewNazwy.csv"
gatunek = pd.read_csv(plik_gatunek, engine = "python")
nazwy = pd.read_csv(plik_nazwy, engine = "python")
nazwy_gatunek = pd.merge(gatunek, nazwy, on = 'id_odmiany', how = 'outer')
 
print(nazwy_gatunek)

Efekt będzie taki:

===================== RESTART: F:\python38\Web scraping 11.py ====================
  id_odmiany                   Gatunek – nazwa angielska    – nazwa botaniczna – ostateczna           – hodowlana         – w badaniach      Status nazwy Data zgł. nazwy Data opubl. nazwy Data zatw. nazwy
0   odmiana1                 Kukurydza             Maize           Zea mays L.     Aramillo             LEKG 1215             LEKG 1215  Z – Zatwierdzona      05.06.2006        15.07.2006       22.02.2007
1   odmiana2                 Kukurydza             Maize           Zea mays L.       Centos               TDR0814               TDR0814  Z – Zatwierdzona      29.06.2019        31.07.2019       13.03.2020
2   odmiana3  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.        Belka              HDP 0135              HDP 0135  Z – Zatwierdzona      31.08.2011        15.11.2011       19.09.2014
3   odmiana4  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.        Wrona  WHJ 664 (WHJ 664/90)  WHJ 664 (WHJ 664/90)  Z – Zatwierdzona                                         05.06.1998
4   odmiana5  Pszenica zwyczajna ozima      Winter Wheat  Triticum aestivum L.       Platon         GRUS 060125.2         GRUS 060125.2  Z – Zatwierdzona      11.01.2012        15.01.2012       08.03.2012
5   odmiana7                     Melon             Melon       Cucumis melo L.         Boss               LNB 107               LNB 107  Z – Zatwierdzona                        30.04.2003       10.02.2005
6   odmiana9                     Melon             Melon       Cucumis melo L.       Emirat               WWZ 547               WWZ 547  Z – Zatwierdzona                                         15.03.1996
7  odmiana10                     Melon             Melon       Cucumis melo L.       Senior               LTR 789               LTR 789  Z – Zatwierdzona      09.05.2007        15.05.2007       16.02.2010
8  odmiana11                     Melon             Melon       Cucumis melo L.      Materac               AGD 555               AGD 555  Z – Zatwierdzona                                         23.02.1998
9  odmiana12                     Melon             Melon       Cucumis melo L.       Czarna               AGD 221               AGD 221  Z – Zatwierdzona                                         28.03.1990
>>> 

Fajnie nie? Ale nie będziemy używać tej opcji w dalszej części, im więcej danych, tym gorzej będzie się zachowywać terminal.
Dwie tabele mamy połączone. Oczywiście nie będziemy wypisywać wszystkich nazw plików .csv, niech sobie Python sam je odczyta. Napiszmy program, który odczyta z katalogu domyślnego nazwy plików .csv. Jeśli masz w nim inne pliki .csv, niż te, które zapisaliśmy w kursie, usuń je. Popatrz na taki program:

import os

print(os.listdir())

W 1 linijce importujesz moduł os.
W 2 linijce korzystasz z funkcji .listdir() do wydrukowania wszystkich plików znajdujących się w domyślnym katalogu. Ta lista może wyglądać tak:

===================== RESTART: F:\python38\Web scraping 11.py ====================
['ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv', 'ctl00_ContentPlaceHolderZawartosc_DetailsViewNazwy.csv', 'ctl00_ContentPlaceHolderZawartosc_DetailsViewStatusy.csv', 'ctl00_ContentPlaceHolderZawartosc_GridViewHodowcyKR.csv', 'ctl00_ContentPlaceHolderZawartosc_GridViewWnioskiKR.csv', 'DLLs', 'Doc', 'drukuj.bmp', 'geckodriver.exe', 'geckodriver.log', 'hvuivi.py', 'include', 'Lib', 'libs', 'LICENSE.txt', 'NEWS.txt', 'prosty przyklad.py', 'python.exe', 'python3.dll', 'python38.dll', 'pythonw.exe', 'rozkład dwumianowy.py', 'rozkład normalny 01.py', 'rozkład normalny 02 towarddatascience.py', 'rozkład normalny.py', 'Scripts']

Nas interesują tylko pliki z rozszerzeniem .csv. Przeróbmy program tak, by wyświetlał tylko te pliki:

import os

lista_csv = []
for plik in os.listdir():
    if plik.endswith(".csv"):
        lista_csv.append(plik)
        
print(lista_csv)

W 3 linijce przygtowujemy pustą listę, na której będą zapisywane nazwy plików.
W 4 linijce iterujemy po każdej nazwie pliku w katalogu
W 5 linijce używamy instrukcji warunkowej wraz z metodą .endswith(). Metoda ta, sprawdza czy string kończy się na podaną w argumencie wartość. W naszym wypadku sprawdza, czy nazwa pliku kończy się na .csv. Jeśli tak to:
W 6 linijce zapisujemy taką nazwę na liście.
W 8 linijce sprawdzamy co na liście się znalazło.
U mnie na liście jest:

===================== RESTART: F:\python38\Web scraping 11.py ====================
['ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv', 'ctl00_ContentPlaceHolderZawartosc_DetailsViewNazwy.csv', 'ctl00_ContentPlaceHolderZawartosc_DetailsViewStatusy.csv', 'ctl00_ContentPlaceHolderZawartosc_GridViewHodowcyKR.csv', 'ctl00_ContentPlaceHolderZawartosc_GridViewWnioskiKR.csv']
>>> 

No to skoro Python przygotował nam taką piękną listę nazw plików, połączmy ich zawartość w jeden nowy dataframe. Pomyśl jak można to zrobić. Ja mam taką propozycję:

import pandas as pd
import os

plik_startowy = "ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv"
lista_csv = []
#przygotuj listę plików z danymi
for plik in os.listdir():
    if plik.endswith(".csv"):
        lista_csv.append(plik)
#załaduj do dataframe pierwszy plik
wszystkie_odmiany = pd.read_csv(plik_startowy, engine = "python")
for nazwa in lista_csv:
    #dodaj do dataframe wszystkie pliki za wyjątkiem pierwszego
    if nazwa != plik_startowy:
        df = pd.read_csv(nazwa, engine = "python")
        wszystkie_odmiany = pd.merge(wszystkie_odmiany, df, on = 'id_odmiany', \
                                     how = 'outer')

print(wszystkie_odmiany)

W 4 linijce wybieramy plik startowy. Pamiętaj, że funkcja merge() łączy dwa dataframe i potrzebujemy pierwszego dataframe, by móc do niego dołączyć kolejne.
W 11 linijce do naszego dataframe nazwanego wszystkie_odmiany wczytujemy dane z pliku startowego.
W 12 linijce zaczyna się pętla, ale
W 14 linijce, z użyciem instrukcji warunkowej if, wykluczamy plik startowy, nie chcemy mieć go dwukrotnie, prawda?
W 15 linijce pod zmienną df wczytujemy kolejny plik .csv
W 16 linijce pod zmienną wszystkie_odmiany wstawiamy dotychczasową zawartość zmiennej wszystkie_odmiany rozszerzoną o df, zawierający kolejną tabelę.
Jeśli wydaje ci się ten sposób aktualizowania wartości zmiennej nieco zagmatwany, popatrz na ten przykład, może będzie bardziej czytelny:

>>> lista = ["a", "b", "c"]
>>> dodatek_1 = ["d", "e", "f"]
>>> dodatek_2 = ["g", "h", "i"]
>>> print(lista)
['a', 'b', 'c']
>>> lista = lista + dodatek_1
>>> print(lista)
['a', 'b', 'c', 'd', 'e', 'f']
>>> lista = lista + dodatek_2
>>> print(lista)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
>>> 

No i zobaczmy co nasz program pobrał i jak wygląda dataframe ze wszystkimi tabelami odmian!

========================== RESTART: F:\python38\Web scraping 11.py ==========================
   id_odmiany                   Gatunek  ... Powód wycofania/odrzucenia Unnamed: 7
0    odmiana1                 Kukurydza  ...                        NaN        NaN
1    odmiana1                 Kukurydza  ...                        NaN        NaN
2    odmiana1                 Kukurydza  ...                        NaN        NaN
3    odmiana2                 Kukurydza  ...                        NaN        NaN
4    odmiana2                 Kukurydza  ...                        NaN        NaN
5    odmiana2                 Kukurydza  ...                        NaN        NaN
6    odmiana2                 Kukurydza  ...                        NaN        NaN
7    odmiana3  Pszenica zwyczajna ozima  ...                        NaN        NaN
8    odmiana3  Pszenica zwyczajna ozima  ...                        NaN        NaN
9    odmiana3  Pszenica zwyczajna ozima  ...                        NaN        NaN
10   odmiana4  Pszenica zwyczajna ozima  ...                               wybierz
11   odmiana4  Pszenica zwyczajna ozima  ...                               wybierz
12   odmiana4  Pszenica zwyczajna ozima  ...                               wybierz
13   odmiana4  Pszenica zwyczajna ozima  ...                               wybierz
14   odmiana5  Pszenica zwyczajna ozima  ...                        NaN        NaN
15   odmiana5  Pszenica zwyczajna ozima  ...                        NaN        NaN
16   odmiana5  Pszenica zwyczajna ozima  ...                        NaN        NaN
17   odmiana7                     Melon  ...                        NaN        NaN
18   odmiana7                     Melon  ...                        NaN        NaN
19   odmiana9                     Melon  ...                        NaN        NaN
20  odmiana10                     Melon  ...                        NaN        NaN
21  odmiana11                     Melon  ...                        NaN        NaN
22  odmiana12                     Melon  ...                        NaN        NaN

[23 rows x 26 columns]

Po pierwsze niewiele widać, po drugie, np. odmiana1, odmiana2 są wypisane 3 razy! Czy coś nam nie wyszło? Wyeksportujmy dataframe do pliku excela, ot tak dla (hehe) odmiany! Polecenie jest całkiem proste:

import pandas as pd
import os

plik_startowy = "ctl00_ContentPlaceHolderZawartosc_DetailsViewGatunek.csv"
lista_csv = []
#przygotuj listę plików z danymi
for plik in os.listdir():
    if plik.endswith(".csv"):
        lista_csv.append(plik)
#załaduj do dataframe pierwszy plik
wszystkie_odmiany = pd.read_csv(plik_startowy, engine = "python")
for nazwa in lista_csv:
    #dodaj do dataframe wszystkie pliki za wyjątkiem pierwszego
    if nazwa != plik_startowy:
        df = pd.read_csv(nazwa, engine = "python")
        wszystkie_odmiany = pd.merge(wszystkie_odmiany, df, on = 'id_odmiany', \
                                     how = 'outer')

wszystkie_odmiany.to_excel("wszystkie_odmiany.xlsx")

W 19 linijce używamy funkcji to_excel(), w której jako argument podajemy nazwę pliku. Jeśli nie chcesz użyć funkcji to_excel(), możesz ją zastąpić funkcją to_csv(). Efekt jest taki:

========================== RESTART: F:\python38\Web scraping 11.py ==========================
Traceback (most recent call last):
  File "F:\python38\Web scraping 11.py", line 28, in <module>
    wszystkie_odmiany.to_excel("wszystkie_odmiany.xlsx")
  File "F:\python38\lib\site-packages\pandas\core\generic.py", line 2175, in to_excel
    formatter.write(
  File "F:\python38\lib\site-packages\pandas\io\formats\excel.py", line 726, in write
    writer = ExcelWriter(stringify_path(writer), engine=engine)
  File "F:\python38\lib\site-packages\pandas\io\excel\_openpyxl.py", line 18, in __init__
    from openpyxl.workbook import Workbook
ModuleNotFoundError: No module named 'openpyxl'
>>> 

ModuleNotFoundError: No module named 'openpyxl’ oznacza, że musimy doinstalować odpowiedni moduł. Otwórz linię komend i wydaj polecenie pip install openpyxl. Uruchom program jeszcze raz. Odnajdź i otwórz plik. Przyjrzyj się i znajdź powód, dla którego odmiany czasem występują w wielu powtórzeniach. A ja już spróbuję to wyjaśnić. Zamieszczę tu wycinek tabeli:

id_odmianyGatunekRodzaj_xKodNazwa
odmiana1Kukurydzazachowujący654Lima, spółka jaskółka
odmiana1Kukurydzahodowca654Lima, spółka jaskółka
odmiana1Kukurydzareprezentant554Saruman ltd. oddział pod lasem

Jak wspominałem, sposób scalania dataframe „outer” zachowuje wszystkie informacje z obu tabeli. Jak widzisz w tabeli „hodowcykr” dla odmiany1, były trzy wartości i funkcja merge() musiała wszystkie trzy wartości do czegoś dopisać, dlatego powtórzone są trzykrotnie dane z tabeli, gdzie odmiana1 występuje raz. Nasz zleceniodawca wciąż ma pełną i prawdziwą informację, co prawda czasem powtórzoną. Popatrz jeszcze na odmianę 4, powtórzoną 4 razy. Tutaj z tabeli „hodowcykr” mamy zachowującego i hodowcę i a z tabeli „wnioskikr” dwa rodzaje wniosków – R i SR. Funkcja merge() musiała scalić „każde z każdym”, na zasadzie:
aa – zachowujący, R
ab – zachowujący, SR
ba – hodowca, R
bb – hodowca, SR
Dlatego wierszy jest aż 4. Taka powtarzalność nie występuje dla odmian 9-12, tam w każdej z tabel był tylko jeden wiersz danych dla jednej odmiany.

Jak widzisz obie metody mają swoje słabości, albo podajemy dane w osobnych plikach, albo dane robią się częściowo powtarzalne. Płaskie tabele nie nadają się zbyt dobrze do przechowywania takich danych. W drugiej połowie kursu (Tak! To koniec pierwszej połowy!) przybliżę ci czym są relacyjne bazy danych i dlaczego nie trzeba się ich bać.

Zadanie Domowe

Podążanie za instrukcjami, nawet jeśli je wszystkie wykonujesz samodzielnie, nie zrobi z ciebie programisty. Zadania domowe mogą wydawać się na początku trudne. Tu nie ma rozwiązania podanego na talerzu, użyj dowolnych źródeł, by znaleźć odpowiedź.

Popatrz na ten kod i uruchom go:

from urllib.request import urlopen
import pandas as pd
pd.options.display.width = 0

strona = "https://inferiordatascience.com/odmiana1/"

df = pd.read_html(strona)
print(df)

Niezłe co? Poeksperymentuj trochę

  1. Czy uda ci się wyświetlić tylko pierwszą tabelę?
  2. A może potrafisz je zapisać, po kolei każdą, do pliku .csv?
  3. Czy uda ci się przenieść nagłówki tabeli „gatunek” z pierwszej kolumny do pierwszego wiersza?
0 0 votes
Ocena artykułu

0 komentarzy
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
0
Chcesz podzielić się komentarzem?x