06 - Biblioteka `pandas` cz. 2: `DataFrame`
Obiekt typu DataFrame
, co się tłumaczy jako ramka danych, jak wspomniałem wcześniej, można w uproszczeniu porównać do tabel znanych np. z arkuszy kalkulacyjnych.
Przechowują dane w kolumnach i rzędach, ale choć kolumny zawierają dane jednego typu, każda kolumna może zawierać dane innego typu. Kolumny, które odpowiadają obiektom typu Series
mają ,,nagłówki’’ (a także indeksy), do których możemy się odwoływać np. przy selekcji danych.
Rzędy mają również indeksy, a także mogą posiadać etykiety, których używamy tak jak w przypadku Series
.
Tworzenie ramek danych
Ramki danych można utworzyć w różny sposób.
Często tworzymy je przy odczycie danych z plików, np. w formacie csv
co opiszę w dalszej części, ale można je też tworzyć ,,od zera’’.
Zacznijmy od utworzenia pustej ramki danych:
import pandas as pd
ramka = pd.DataFrame()
print(ramka)
Empty DataFrame
Columns: []
Index: []
Teraz stwórzmy ramkę danych, używając słownika list. Na razie będzie ona zawierała kilka gatunków organizmów i liczby (2n) chromosomów:
import pandas as pd
slownik_list = {'Gatunek': ['Myrmecia pilosula',
'Ophioglossum reticulatum',
'Canis familiaris',
'Homo sapiens',
'Arabidopsis thaliana'
],
'L_chr': [2, 1400, 36, 46, 10]
}
dane = pd.DataFrame(slownik_list)
print(dane)
Gatunek L_chr
0 Myrmecia pilosula 2
1 Ophioglossum reticulatum 1400
2 Canis familiaris 36
3 Homo sapiens 46
4 Arabidopsis thaliana 10
Jak widać, klucze w słowniku zostały przekształcone w nazwy kolumn.
Uwaga: jeśli używasz Jupyter-lab
, a wydrukowanie ramki jest ostatnim poleceniem w uruchamianej komórce, to zamiast print(ramka)
możesz pisać po prostu ramka
- wyświetli się w estetyczniejszej formie.
Kolejne rzędy posiadają indeksy, ale można im przypisać etykiety rzędów, podobnie jak elementom obiektu Series
:
dane.index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek', 'rzodkiewnik']
print(dane)
Gatunek L_chr
mrówka Myrmecia pilosula 2
nasięźrzał Ophioglossum reticulatum 1400
pies Canis familiaris 36
człowiek Homo sapiens 46
rzodkiewnik Arabidopsis thaliana 10
Oczywiście etykiety można przypisać od razu, przy tworzeniu ramki:
dane = pd.DataFrame(slownik_list, index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek', 'rzodkiewnik'])
print(dane)
Gatunek L_chr
mrówka Myrmecia pilosula 2
nasięźrzał Ophioglossum reticulatum 1400
pies Canis familiaris 36
człowiek Homo sapiens 46
rzodkiewnik Arabidopsis thaliana 10
Przy tworzeniu ramki, można zmienić kolejność kolumn, a także dodać nowe.
Jeśli nie będą im przypisane dane, zostaną wypełnione wartościami NaN
:
dane = pd.DataFrame(slownik_list,
index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek', 'rzodkiewnik'],
columns = ['L_chr', 'Gatunek', 'Wielkosc_genomu'])
print(dane)
L_chr Gatunek Wielkosc_genomu
mrówka 2 Myrmecia pilosula NaN
nasięźrzał 1400 Ophioglossum reticulatum NaN
pies 36 Canis familiaris NaN
człowiek 46 Homo sapiens NaN
rzodkiewnik 10 Arabidopsis thaliana NaN
Jeśli nie uwzględnimy nazwy, któregoś z elementu słownika, seria danych nie zostanie uwzględniona:
dane = pd.DataFrame(slownik_list,
index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek', 'rzodkiewnik'],
columns = ['Gatunek', 'Wielkosc_genomu'])
print(dane)
Gatunek Wielkosc_genomu
mrówka Myrmecia pilosula NaN
nasięźrzał Ophioglossum reticulatum NaN
pies Canis familiaris NaN
człowiek Homo sapiens NaN
rzodkiewnik Arabidopsis thaliana NaN
Ramki z danymi można utworzyć także na różne inne sposoby, np:
# Ramka danych z listy słowników:
lista_slownikow = [{'Gatunek': 'Myrmecia pilosula', 'L_chr': 2},
{'Gatunek': 'Ophioglossum reticulatum', 'L_chr': 1400},
{'Gatunek': 'Canis familiaris', 'L_chr': 36},
{'Gatunek': 'Homo sapiens', 'L_chr': 46},
{'Gatunek': 'Arabidopsis thaliana', 'L_chr': 10}]
dane = pd.DataFrame(lista_slownikow,
index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek', 'rzodkiewnik'],)
print(dane)
Gatunek L_chr
mrówka Myrmecia pilosula 2
nasięźrzał Ophioglossum reticulatum 1400
pies Canis familiaris 36
człowiek Homo sapiens 46
rzodkiewnik Arabidopsis thaliana 10
# Ramka danych z listy krotek:
lista_krotek = [('Myrmecia pilosula', 2),
('Ophioglossum reticulatum', 1400),
('Canis familiaris', 36),
('Homo sapiens', 46),
('Arabidopsis thaliana', 10)]
dane = pd.DataFrame(lista_krotek,
columns = ['Gatunek', 'L_chr'],
index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek', 'rzodkiewnik'])
print(dane)
Gatunek L_chr
mrówka Myrmecia pilosula 2
nasięźrzał Ophioglossum reticulatum 1400
pies Canis familiaris 36
człowiek Homo sapiens 46
rzodkiewnik Arabidopsis thaliana 10
# Ramka z obiektów Series
gatunki = pd.Series(['Myrmecia pilosula',
'Ophioglossum reticulatum',
'Canis familiaris',
'Homo sapiens',
'Arabidopsis thaliana'])
chromosomy = pd.Series([2, 1400, 36, 46, 10])
dane = pd.DataFrame({'Gatunek': gatunki, 'L_chr': chromosomy})
dane.index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek', 'rzodkiewnik']
print(dane)
Gatunek L_chr
mrówka Myrmecia pilosula 2
nasięźrzał Ophioglossum reticulatum 1400
pies Canis familiaris 36
człowiek Homo sapiens 46
rzodkiewnik Arabidopsis thaliana 10
Proste pobieranie kolumn i rzędów
Obiekty DataFrame
cieszą się dużą popularnością między innymi dlatego, ze biblioteka pandas
umożliwia dużą swobodę i efektywność w selekcji danych. Na razie zobaczmy jak działa proste wybieranie kolumn i rzędów, później przejdziemy do bardziej złożonych zadań.
Najpierw stwórzmy (ponownie) ramkę danych, na których będziemy dalej pracować:
import pandas as pd
slownik_list = {'Gatunek': ['Myrmecia pilosula',
'Ophioglossum reticulatum',
'Canis familiaris',
'Homo sapiens',
'Arabidopsis thaliana'
],
'L_chr': [2, 1400, 36, 46, 10]
}
dane = pd.DataFrame(slownik_list,
index = ['mrówka', 'nasięźrzał',
'pies', 'człowiek', 'rzodkiewnik'])
print(dane)
Gatunek L_chr
mrówka Myrmecia pilosula 2
nasięźrzał Ophioglossum reticulatum 1400
pies Canis familiaris 36
człowiek Homo sapiens 46
rzodkiewnik Arabidopsis thaliana 10
Poszczególne kolumny możemy pobierać używając nazw kolumn, na dwa sposoby:
print(dane['Gatunek'])
print()
print(dane.L_chr)
mrówka Myrmecia pilosula
nasięźrzał Ophioglossum reticulatum
pies Canis familiaris
człowiek Homo sapiens
rzodkiewnik Arabidopsis thaliana
Name: Gatunek, dtype: object
mrówka 2
nasięźrzał 1400
pies 36
człowiek 46
rzodkiewnik 10
Name: L_chr, dtype: int64
Ten drugi sposób (ramka.nazwa_kolumny) sprawdzi się jednak tylko wtedy, jeśli nazwa kolumny będzie zgodna z zasadami nazw zmiennych w języku Python. Zatem nie powinna zawierać np. spacji.
Przyjrzyj się, w jaki sposób wyświetlana jest zawartość kolumny, coś nam to przypomina. Sprawdźmy typ otrzymanego obiektu:
print(type(dane['Gatunek']))
print(type(dane['L_chr']))
<class 'pandas.core.series.Series'>
<class 'pandas.core.series.Series'>
Jak widać, otrzymujemy obiekt typu Series
, co wskazuje na sposób pracy z nim.
Zwróć uwagę, że niezależnie od wybranej kolumny, dane w seriach które otrzymujemy, są oznaczone etykietami z ramki danych.
Rząd możemy pobrać używając atrybutu loc
i etykiety lub iloc
z wartością indeksu:
print(dane.loc['pies'])
print()
print(dane.iloc[3])
Gatunek Canis familiaris
L_chr 36
Name: pies, dtype: object
Gatunek Homo sapiens
L_chr 46
Name: człowiek, dtype: object
Dodawanie, modyfikacja i usuwanie kolumn
Do ramki danych łatwo możemy dodać kolejne kolumny. Można to zrobić na różne sposoby. Najpierw odtwórzmy ramkę, jeśli to konieczne:
import pandas as pd
slownik_list = {'Gatunek': ['Myrmecia pilosula',
'Ophioglossum reticulatum',
'Canis familiaris',
'Homo sapiens',
'Arabidopsis thaliana'
],
'L_chr': [2, 1400, 36, 46, 10]
}
dane = pd.DataFrame(slownik_list,
index = ['mrówka', 'nasięźrzał', 'pies',
'człowiek', 'rzodkiewnik'])
print(dane)
Gatunek L_chr
mrówka Myrmecia pilosula 2
nasięźrzał Ophioglossum reticulatum 1400
pies Canis familiaris 36
człowiek Homo sapiens 46
rzodkiewnik Arabidopsis thaliana 10
# Sposób 1
nowe_dane_1 = ['Nie', 'Tak', 'Tak', 'Nie', 'Tak']
dane['Autotrof'] = nowe_dane_1
print()
print(dane)
Gatunek L_chr Autotrof
mrówka Myrmecia pilosula 2 Nie
nasięźrzał Ophioglossum reticulatum 1400 Tak
pies Canis familiaris 36 Tak
człowiek Homo sapiens 46 Nie
rzodkiewnik Arabidopsis thaliana 10 Tak
# Sposób 2
nowe_dane_2 = ['zwierzęta', 'rośliny', 'zwierzęta', 'zwierzęta', 'rośliny']
dane.insert(1, 'Krolestwo', nowe_dane_2, False)
print()
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 Nie
nasięźrzał Ophioglossum reticulatum rośliny 1400 Tak
pies Canis familiaris zwierzęta 36 Tak
człowiek Homo sapiens zwierzęta 46 Nie
rzodkiewnik Arabidopsis thaliana rośliny 10 Tak
Pierwszy sposób pozwala na dołączenie nowej kolumny na końcu ramki.
Drugi jest nieco bardziej złożony.
Metoda insert()
przyjęła cztery argumenty:
insert(indeks, nazwa kolumny, dane, możliwość_duplikatów)
Indeks wskazuje, przed którą kolumną wstawić nowe dane.
Ostatni argument (domyślnie jest to False
, zatem można było go w tym przypadku pominąć) określa, czy wprowadzana kolumna może się duplikować. Sprawdź, co się stanie, jeśli zmienisz argument na True
i ponownie uruchomisz kod.
Możemy łatwo zmodyfikować zawartość całej kolumny, odwołując się do jej nazwy i podając nowe wartości:
nowe_dane_2 = [False, True, True, False, True]
dane['Autotrof'] = nowe_dane_2
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
Dodanie nowej kolumny można połączyć z wypełnianiem jej wartości z użyciem danych z innej kolumny, np. dodajmy kolumnę n
zawierającą liczbę n
(haploidalną) chromosomów. Możemy te wartości wyliczyć, dzieląc liczby pobrane z kolumny L-chromosomow
, która zawiera liczby 2n
chromosomów:
dane['n'] = dane['L_chr']/2
print(dane)
Gatunek Krolestwo L_chr Autotrof n
mrówka Myrmecia pilosula zwierzęta 2 False 1.0
nasięźrzał Ophioglossum reticulatum rośliny 1400 True 700.0
pies Canis familiaris zwierzęta 36 True 18.0
człowiek Homo sapiens zwierzęta 46 False 23.0
rzodkiewnik Arabidopsis thaliana rośliny 10 True 5.0
Jak widać, otrzymaliśmy nową kolumnę z danymi, jednak ma ona typ liczb zmiennoprzecinkowych co nie ma tu sensu. Przeprowadźmy zatem ponownie operację, tym razem ustawiając typ ‘int64`:
dane['n'] = (dane['L_chr']/2).astype('int64')
print(dane)
Gatunek Krolestwo L_chr Autotrof n
mrówka Myrmecia pilosula zwierzęta 2 False 1
nasięźrzał Ophioglossum reticulatum rośliny 1400 True 700
pies Canis familiaris zwierzęta 36 True 18
człowiek Homo sapiens zwierzęta 46 False 23
rzodkiewnik Arabidopsis thaliana rośliny 10 True 5
Niepotrzebną kolumnę można usunąć, używając metody drop()
. Zwracana jest nowa ramka, zatem jeśli chcemy zachować starą nazwę, przypisujemy ramkę do niej. Parametr axis
pozwala wybrać między kolumnami i rzędami. Wartość 1
oznacza kolumny, możemy też użyć wyrażenia axis = 'columns'
:
dane = dane.drop('n', axis = 1)
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
Dodawanie, modyfikacja i usuwanie rzędów
Zacznijmy od odtworzenia ramki danych:
import pandas as pd
slownik_list = {'Gatunek': ['Myrmecia pilosula',
'Ophioglossum reticulatum',
'Canis familiaris',
'Homo sapiens',
'Arabidopsis thaliana'
],
'Krolestwo': ['zwierzęta', 'rośliny', 'zwierzęta',
'zwierzęta', 'rośliny'],
'L_chr': [2, 1400, 36, 46, 10],
'Autotrof': [False, True, True, False, True]
}
dane = pd.DataFrame(slownik_list,
index = ['mrówka', 'nasięźrzał', 'pies',
'człowiek', 'rzodkiewnik'])
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
Dodanie rzędu(ów), podobnie jak w przypadku kolumn, można wykonać na różne sposoby. Pierwszym jest zastosowanie funkcji concat()
, pozwalającej połączyć ramki danych (dwie, lub więcej). Co ważne, funkcja concat()
nie dołącza nowych danych do istniejącej ramki, ale łączy ramki, tworząc nową ramkę danych. Jeśli chcemy zachować starą nazwę ramki, to trzeba do niej przypisać wynik łączenia ramek. Tu jednak utworzymy nową ramkę:
# Funkcja concat() - łączenie ramek
nowy_rzad = pd.DataFrame({
'Gatunek': 'Orobanche macrolepis',
'L_chr': 76,
'Krolestwo': 'rosliny',
'Autotrof': False
}, index=['zaraza'])
nowe_dane = pd.concat([dane, nowy_rzad])
print(nowe_dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
zaraza Orobanche macrolepis rosliny 76 False
Zwróć uwagę, co się stanie, jeśli połączymy ramki nie posiadające etykiety rzędów, a tylko numery indeksów:
import pandas as pd
ramka_1 = pd.DataFrame({'Gatunek': ['Myrmecia pilosula',
'Ophioglossum reticulatum',
],
'L_chr': [2, 1400]
})
ramka_2 = pd.DataFrame({'Gatunek': [
'Canis familiaris',
'Homo sapiens',
'Arabidopsis thaliana'
],
'L_chr': [36, 46, 10]
})
dane_zlozone = pd.concat([ramka_1, ramka_2])
print(dane_zlozone)
Gatunek L_chr
0 Myrmecia pilosula 2
1 Ophioglossum reticulatum 1400
0 Canis familiaris 36
1 Homo sapiens 46
2 Arabidopsis thaliana 10
Jak widać, numery indeksów, odziedziczone po pierwotnych ramkach, powtarzają się, co zazwyczaj nie jest pożądane.
Aby tego uniknąć, należy dodać argument ignore_index=True
:
dane_zlozone = pd.concat([ramka_1, ramka_2], ignore_index=True)
print(dane_zlozone)
Gatunek L_chr
0 Myrmecia pilosula 2
1 Ophioglossum reticulatum 1400
2 Canis familiaris 36
3 Homo sapiens 46
4 Arabidopsis thaliana 10
Wróćmy do ramki dane
. Dodajmy do niej nowe dane (a właściwie stwórzmy nową ramkę z połączenia dane
i nowej ramki):
nowy_rzad = pd.DataFrame({
'Gatunek': 'Cuscuta campestris',
'Krolestwo': 'rośliny',
'Autotrof': False
}, index=['kanianka'])
nowe_dane = pd.concat([dane, nowy_rzad])
print(nowe_dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzeta 2.0 False
nasiezrzal Ophioglossum reticulatum rosliny 1400.0 True
pies Canis familiaris zwierzeta 36.0 True
czlowiek Homo sapiens zwierzeta 46.0 False
rzodkiewnik Arabidopsis thaliana rosliny 10.0 True
kanianka Cuscuta campestris rosliny NaN False
Dodając Cuscuta campestris nie podaliśmy liczby chromosomów (tak naprawdę jest ona znana i wynosi 2n = 56). Zauważ, że w kolumnie L_chr
pojawiła się wartość NaN
(brak danych) a pozostałe liczby w kolumnie zmieniły się z całkowitych, na zmiennoprzecinkowe. Na razie jednak tylko wydrukowaliśmy uzupełnioną kopię ramki dane
, nie zmieniliśmy jej.
Teraz użyjemy loc
aby dodać dane dla drożdży. Tym razem efektem będzie modyfikacja oryginalnej ramki danych.
# loc
dane.loc['drożdże'] = {'Gatunek': 'Saccharomyces cerevisiae',
'L_chr': 32,
'Krolestwo': 'grzyby',
'Autotrof': False}
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
zaraza Orobanche macrolepis rosliny 76 False
drożdże Saccharomyces cerevisiae grzyby 32 False
Dzięki loc
dodaliśmy na końcu rząd danych opatrzonych etykietą podaną w parze nawiasów kwadratowych.
loc
można także użyć w celu podmiany danych:
dane.loc['zaraza'] = {'Gatunek': 'Orobanche cernua',
'L_chr': 38,
'Krolestwo': 'rosliny',
'Autotrof': False
}
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
zaraza Orobanche cernua rosliny 38 False
drożdże Saccharomyces cerevisiae grzyby 32 False
iloc
pozwala podmienić rząd danych w miejscu wskazanym przez indeks podany w parze nawiasów kwadratowych:
dane.iloc[5] = {'Gatunek': 'Cuscuta campestris',
'Krolestwo': 'rośliny',
'L_chr': 56,
'Autotrof': False}
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
zaraza Cuscuta campestris rośliny 56 False
drożdże Saccharomyces cerevisiae grzyby 32 False
Zauważ, że choć zmieniły się dane, pozostała stara nazwa rzędu. Cuscuta to nie jest zaraza, ale kanianka, zatem powinniśmy zmienić etykietę:
dane.rename(index={'zaraza': 'kanianka'}, inplace=True)
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
kanianka Cuscuta campestris rośliny 56 False
drożdże Saccharomyces cerevisiae grzyby 32 False
Ustawienie inplace=True
powoduje, że zmienia się ramka, ustawienie inplace=False
(False
jest domyślną wartością parametru inplace
), powoduje, że ramka się nie zmienia, ale zwracana jest zmodyfikowana kopia ramki.
Rząd można usunąć za pomocą metody drop()
, w tym przypadku jednak axis
powinien przyjąć wartość 0
, co odpowiada rzędom, można też wpisać rows
, można także po prostu pominąć ten parametr, ponieważ jego domyślna wartość to właśnie 0
:
print(dane.drop('pies', axis = 'rows'))
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
kanianka Cuscuta campestris rośliny 56 False
drożdże Saccharomyces cerevisiae grzyby 32 False
Pobieranie i modyfikacja danych w konkretnych komórkach
Zacznijmy od utworzenia ramki (o ile to konieczne):
import pandas as pd
slownik_list = {'Gatunek': ['Myrmecia pilosula',
'Ophioglossum reticulatum',
'Canis familiaris',
'Homo sapiens',
'Arabidopsis thaliana',
'Cuscuta campestris',
'Saccharomyces cerevisiae'],
'Krolestwo': ['zwierzęta', 'rośliny', 'zwierzęta', 'zwierzęta',
'rośliny', 'rośliny', 'grzyby'],
'L_chr': [2, 1400, 36, 46, 10, 56, 32],
'Autotrof': [False, True, True, False, True, False, False]}
dane = pd.DataFrame(slownik_list,
index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek',
'rzodkiewnik', 'kanianka', 'drożdże'])
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
kanianka Cuscuta campestris rośliny 56 False
drożdże Saccharomyces cerevisiae grzyby 32 False
Pobierać dane z komórek można na różne sposoby:
# Podajemy nazwę kolumny i indeks rzędu
print(dane['Gatunek'][2])
Canis familiaris
# Podajemy nazwę kolumny i etykietę rzędu
print(dane['Gatunek']['pies'])
Canis familiaris
# loc - podajemy etykietę rzędu i nazwę kolumny
print(dane.loc['pies', 'Gatunek'])
Canis familiaris
# iloc - Podajemy indeks rzędu i indeks kolumny
print(dane.iloc[2,0])
Canis familiaris
Modyfikować zawartość komórki możemy np. tak:
# Podajemy etykietę rzędu i nazwę kolumny
dane.at['pies', 'Gatunek'] = 'Pieskus domestucus'
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
pies Pieskus domestucus zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
kanianka Cuscuta campestris rośliny 56 False
drożdże Saccharomyces cerevisiae grzyby 32 False
# Podajemy etykietę rzędu i nazwę kolumny
dane.loc['pies', 'Gatunek'] = 'Pieszczochus kanapus'
print(dane.loc['pies'])
Gatunek Pieszczochus kanapus
Krolestwo zwierzęta
L_chr 36
Autotrof True
Name: pies, dtype: object
Przywróćmy właściwą nazwę psu, używając odwołania do indeksu rzędu i kolumny:
# Podajemy indeks rzędu i indeks kolumny
dane.iloc[2,0] = "Canis familiaris"
print(dane.loc['pies'])
Gatunek Canis familiaris
Krolestwo zwierzęta
L_chr 36
Autotrof True
Name: pies, dtype: object
Przy okazji naprawmy rażący błąd w naszych danych: pies przecież nie jest autotrofem!
dane.iloc[2,3] = False
print(dane.loc['pies'])
Gatunek Canis familiaris
Krolestwo zwierzęta
L_chr 36
Autotrof False
Name: pies, dtype: object
Selekcja danych w kolumnach i rzędach
Tradycyjnie zacznijmy od odtworzenia ramki:
import pandas as pd
slownik_list = {'Gatunek': ['Myrmecia pilosula',
'Ophioglossum reticulatum',
'Canis familiaris',
'Homo sapiens',
'Arabidopsis thaliana',
'Cuscuta campestris',
'Saccharomyces cerevisiae'],
'Krolestwo': ['zwierzęta', 'rośliny', 'zwierzęta', 'zwierzęta',
'rośliny', 'rośliny', 'grzyby'],
'L_chr': [2, 1400, 36, 46, 10, 56, 32],
'Autotrof': [False, True, False, False, True, False, False]}
dane = pd.DataFrame(slownik_list,
index = ['mrówka', 'nasięźrzał', 'pies', 'człowiek',
'rzodkiewnik', 'kanianka', 'drożdże'])
Stosunkowo łatwo można wyselekcjonować kilka wybranych kolumn z ramki:
Z użyciem nazw kolumn:
print(dane[['Gatunek', 'Autotrof']])
Gatunek Autotrof
mrówka Myrmecia pilosula False
nasięźrzał Ophioglossum reticulatum True
pies Canis familiaris False
człowiek Homo sapiens False
rzodkiewnik Arabidopsis thaliana True
kanianka Cuscuta campestris False
drożdże Saccharomyces cerevisiae False
Z użyciem indeksów:
print(dane[dane.columns[[0,3]]])
Gatunek Autotrof
mrówka Myrmecia pilosula False
nasięźrzał Ophioglossum reticulatum True
pies Canis familiaris False
człowiek Homo sapiens False
rzodkiewnik Arabidopsis thaliana True
kanianka Cuscuta campestris False
drożdże Saccharomyces cerevisiae False
Także można podać zakres kolumn:
print(dane[dane.columns[0:3]])
Gatunek Krolestwo L_chr
mrówka Myrmecia pilosula zwierzęta 2
nasięźrzał Ophioglossum reticulatum rośliny 1400
pies Canis familiaris zwierzęta 36
człowiek Homo sapiens zwierzęta 46
rzodkiewnik Arabidopsis thaliana rośliny 10
kanianka Cuscuta campestris rośliny 56
drożdże Saccharomyces cerevisiae grzyby 32
W wybieraniu wielu rzędów przydadzą nam się nasi znajomi: loc
oraz iloc
ale można też użyć zakresu indeksów w parze nawiasów kwadratowych:
print(dane[2:5])
Gatunek Krolestwo L_chr Autotrof
pies Canis familiaris zwierzęta 36 False
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
print(dane.loc[['pies', 'mrówka', 'drożdże']])
Gatunek Krolestwo L_chr Autotrof
pies Canis familiaris zwierzęta 36 False
mrówka Myrmecia pilosula zwierzęta 2 False
drożdże Saccharomyces cerevisiae grzyby 32 False
print(dane.iloc[[2, 5, 1]])
Gatunek Krolestwo L_chr Autotrof
pies Canis familiaris zwierzęta 36 False
kanianka Cuscuta campestris rośliny 56 False
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
print(dane.iloc[2:5])
Gatunek Krolestwo L_chr Autotrof
pies Canis familiaris zwierzęta 36 False
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
Można też zawężać wybór do wybranych kolumn i rzędów na raz.
Za pomocą etykiet wierszy i nazw kolumn (loc
)
print(dane.loc[['pies', 'mrówka', 'kanianka'],
['Krolestwo', 'Autotrof']])
Krolestwo Autotrof
pies zwierzęta False
mrówka zwierzęta False
kanianka rośliny False
print(dane.loc['pies': 'kanianka',
:'Krolestwo'])
Gatunek Krolestwo
pies Canis familiaris zwierzęta
człowiek Homo sapiens zwierzęta
rzodkiewnik Arabidopsis thaliana rośliny
kanianka Cuscuta campestris rośliny
A także indeksów (iloc
)
print(dane.iloc[[2, 0, 5], [2, 0]])
L_chr Gatunek
pies 36 Canis familiaris
mrówka 2 Myrmecia pilosula
kanianka 56 Cuscuta campestris
Selekcja danych może się także odbywać na podstawie wartości:
print(dane[dane['L_chr'] > 40])
Gatunek Krolestwo L_chr Autotrof
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
człowiek Homo sapiens zwierzęta 46 False
kanianka Cuscuta campestris rośliny 56 False
print(dane[dane['Krolestwo'] == 'rośliny'])
Gatunek Krolestwo L_chr Autotrof
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
rzodkiewnik Arabidopsis thaliana rośliny 10 True
kanianka Cuscuta campestris rośliny 56 False
Można też tworzyć bardziej złożone wyrażenia, używając operatorów &
(and) czy |
(or).
print(dane[(dane['Krolestwo'] == 'rośliny') & (dane['Autotrof'] == True)])
Gatunek Krolestwo L_chr Autotrof
nasięźrzał Ophioglossum reticulatum rośliny 1400 True
rzodkiewnik Arabidopsis thaliana rośliny 10 True
Znak tyldy (~
) odwraca wartości boolowskie w serii, zatem możemy go użyć w celu odwrócenia filtrowania wartości, na przeciwny:
print(dane[(dane['Krolestwo'] == 'rośliny') & (~dane['Autotrof'] == True)])
Gatunek Krolestwo L_chr Autotrof
kanianka Cuscuta campestris rośliny 56 False
print(dane[(dane['Krolestwo'] == 'zwierzęta') | (dane['L_chr'] < 40)])
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
pies Canis familiaris zwierzęta 36 False
człowiek Homo sapiens zwierzęta 46 False
rzodkiewnik Arabidopsis thaliana rośliny 10 True
drożdże Saccharomyces cerevisiae grzyby 32 False
W końcu możemy połączyć selekcję rzędów i kolumn na podstawie indeksów (lub nazw) oraz wartości w komórkach:
print(dane.iloc[:, [0, 3]][dane['Autotrof'] == False])
Gatunek Autotrof
mrówka Myrmecia pilosula False
pies Canis familiaris False
człowiek Homo sapiens False
kanianka Cuscuta campestris False
drożdże Saccharomyces cerevisiae False
print(dane.loc[:, ['Krolestwo', 'Autotrof']][dane['Autotrof'] == False])
Krolestwo Autotrof
mrówka zwierzęta False
pies zwierzęta False
człowiek zwierzęta False
kanianka rośliny False
drożdże grzyby False
Pobieranie fragmentu ramki przy pomocy loc
i iloc
jest bardziej efektywne.
Przy pobieraniu wycinka ramki, a następnie próbie zmiany w niej wartości, możemy natrafić na pewien problem:
wybrane = dane[dane['Autotrof'] == False]
wybrane['Autotrof']['pies'] = True
print(wybrane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
kanianka Cuscuta campestris rośliny 56 False
drożdże Saccharomyces cerevisiae grzyby 32 False
/tmp/ipykernel_49770/682686734.py:2: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
wybrane['Autotrof']['pies'] = True
Jak widać operacja się w zasadzie udała ale otrzymaliśmy ostrzeżenie (można więcej na ten temat poczytać w wyświetlanym linku).
Aby uniknąć podobnych ostrzeżeń, powinniśmy zrobić dwie rzeczy.
Po pierwsze skopiować wyselekcjonowane dane do osobnej ramki.
Po drugie użyć loc
(lub iloc
) do modyfikacji danych:
wybrane = dane[dane['Autotrof'] == False].copy()
wybrane.loc['pies','Autotrof'] = True
print(wybrane)
Gatunek Krolestwo L_chr Autotrof
mrówka Myrmecia pilosula zwierzęta 2 False
pies Canis familiaris zwierzęta 36 True
człowiek Homo sapiens zwierzęta 46 False
kanianka Cuscuta campestris rośliny 56 False
drożdże Saccharomyces cerevisiae grzyby 32 False
Oczywiście pamiętajmy, że pies NIE jest autotrofem ;-)
Z pobrane serii danych możemy, podobnie jak to robiliśmy na obiektach Series
, wyliczyć różne wartości, używając odpowiednich funkcji, lub metod, np:
chrom_2n = dane['L_chr']
print(chrom_2n)
mrówka 2
nasięźrzał 1400
pies 36
człowiek 46
rzodkiewnik 10
kanianka 56
drożdże 32
Name: L_chr, dtype: int64
print(f'suma: {chrom_2n.sum()}')
print(f'największa: {chrom_2n.max()}')
print(f'średnia: {chrom_2n.mean()}')
print(f'mediana: {chrom_2n.median()}')
suma: 1582
największa: 1400
średnia: 226.0
mediana: 36.0
Można też przeprowadzić te operacje bezpośrednio na kolumnie ramki danych:
print(f'suma: {dane["L_chr"].sum()}')
print(f'największa: {dane["L_chr"].max()}')
print(f'średnia: {dane["L_chr"].mean()}')
print(f'mediana: {dane["L_chr"].median()}')
suma: 1582
najwieksza: 1400
srednia: 226.0
mediana: 36.0
Transpozycja ramki
Ramki (podobnie zresztą jak tablice ndarray
) można łatwo przekształcić tak, że kolumny stają się wierszami a wiersze kolumnami.
Taką operację nazywamy transponowaniem.
Można to wykonać, wykorzystując atrybut T
Odtwórzmy ramkę danych, tym razem nieco mniejszą:
import pandas as pd
slownik_list = {'Gatunek': ['M. pilosula',
'C. familiaris',
'C. campestris',
'S. cerevisiae'],
'Krolestwo': ['zwierzęta', 'zwierzęta',
'rośliny', 'grzyby'],
'L_chr': [2, 36, 56, 32],
'Autotrof': [False, False, False, False]}
dane = pd.DataFrame(slownik_list,
index = ['mrówka', 'pies',
'kanianka', 'drożdże'])
print(dane)
Gatunek Krolestwo L_chr Autotrof
mrówka M. pilosula zwierzęta 2 False
pies C. familiaris zwierzęta 36 False
kanianka C. campestris rośliny 56 False
drożdże S. cerevisiae grzyby 32 False
dane_t = dane.T
print(dane_t)
mrówka pies kanianka drożdże
Gatunek M. pilosula C. familiaris C. campestris S. cerevisiae
Krolestwo zwierzęta zwierzęta rośliny grzyby
L_chr 2 36 56 32
Autotrof False False False False