Python - wprowadzenie

07 - Biblioteka `pandas` cz. 3: ćwiczenia

Wczytanie danych i podstawowe informacje o ramce i danych

Przejdź na stronę https://www.ncbi.nlm.nih.gov/genome/browse#!/organelles/. Znajdziesz tam tabele zawierającą informację na temat sekwencji genomów plastydów i mitochondriów zdeponowanych w bazie GenBank. Na górze kolumny znajdziesz przycisk Choose Columns, kliknij go. Usuń kolumny: Strain, BioSample oraz BioProject. Dodaj kolumny: Genes i Pseudogene. Następnie pobierz dane (przycisk Download) i zapisz w katalogu, w którym będziesz uruchamiać kod. Domyślna nazwa to organelles.csv.

Jeśli nie uda się pobrać danych z powyższej strony, możesz pobrać dane tutaj. Nie są to dane aktualne, ale są odpowiednie do wykonania ćwiczeń.

Otwórz plik w edytorze tekstu. Przyjrzyj się, jak zapisane są w nim dane:

Organism Name,Organism Groups,Size(Mb),GC%,Type,Replicons,CDS,Release Date,Genes,Pseudogene
"Aacanthocnema dobsoni","Eukaryota;Animals;Insects",0.015179,21.9382,"mitochondrion","NC_038132.1/MG989216.1",13,"2018-07-31T00:00:00Z",37,0
"Abacion magnum","Eukaryota;Animals;Other Animals",0.01516,33.4037,"mitochondrion","NC_021932.1/JX437062.1",13,"2013-08-06T00:00:00Z",35,0..

Pierwsza linia, poprzedzona znakiem # (jeśli dane zostały pobrane ze strony NCBI) zawiera nagłówki. W kolejnych zapisane są dane, poprzedzielane przecinkami. Jest to znany nam format zapisu danych csv.

Ciągi znaków, które nie są zapisem liczb, są ujęte w pary cudzysłowów. Usuń znak # z początku pierwszego rzędu, jeśli tam się znajduje i zapisz plik.

Wczytajmy dane:

import pandas as pd
# Wczytanie danych z pliku csv
dane = pd.read_csv('organelles.csv')

Uzyskajmy kilka podstawowych informacji na temat wczytanych danych. Zwłaszcza w przypadku dużych ramek, gdy chcemy podejrzeć ich zawartość, wykorzystujemy metodę head():

# Początek ramki
print(f'Początek ramki:\n{dane.head()}')
Początek ramki:
           Organism Name                  Organism Groups  Size(Mb)      GC%  \
0  Aacanthocnema dobsoni        Eukaryota;Animals;Insects  0.015179  21.9382   
1         Abacion magnum  Eukaryota;Animals;Other Animals  0.015160  33.4037   
2    Abalistes stellaris         Eukaryota;Animals;Fishes  0.016502  44.4189   
3  Abax parallelepipedus        Eukaryota;Animals;Insects  0.017701  20.7446   
4        Abbottina binhi         Eukaryota;Animals;Fishes  0.016609  44.1387   

            Type               Replicons  CDS          Release Date  Genes  \
0  mitochondrion  NC_038132.1/MG989216.1   13  2018-07-31T00:00:00Z     37   
1  mitochondrion  NC_021932.1/JX437062.1   13  2013-08-06T00:00:00Z     35   
2  mitochondrion  NC_011943.1/AP009202.1   13  2009-01-22T00:00:00Z     13   
3  mitochondrion  NC_030592.1/KT876877.1   13  2016-07-12T00:00:00Z     37   
4  mitochondrion  NC_048988.1/MK852688.1   13  2020-06-28T00:00:00Z     37   

   Pseudogene  
0           0  
1           0  
2           0  
3           0  
4           0  

Uwaga: Wyświetlone dane, zwłaszcza liczbowe, do których przejdziemy za chwilę, będą się w mniejszym lub większym stopniu różnić od tych, które przedstawiam. Różnice wynikają z tego, że dane które pobrałeś są już inne, z pewnością znacznie większe niż te, które pobrałem tworząc tę lekcję (wiosna 2021 r.).

Można podać argument, determinujący liczbę zwracanych rzędów:

print(f'Początek ramki:\n{dane.head(2)}')
Początek ramki:
           Organism Name                  Organism Groups  Size(Mb)      GC%  \
0  Aacanthocnema dobsoni        Eukaryota;Animals;Insects  0.015179  21.9382   
1         Abacion magnum  Eukaryota;Animals;Other Animals  0.015160  33.4037   

            Type               Replicons  CDS          Release Date  Genes  \
0  mitochondrion  NC_038132.1/MG989216.1   13  2018-07-31T00:00:00Z     37   
1  mitochondrion  NC_021932.1/JX437062.1   13  2013-08-06T00:00:00Z     35   

   Pseudogene  
0           0  
1           0  

Jak widać, nazwy kolumn zostały pobrane z pierwszego rzędu pliku. Podobnie można sprawdzić, jak kończy się ramka:

# Koniec ramki
print(f'Koniec ramki:\n{dane.tail()}')
Koniec ramki:
                                 Organism Name               Organism Groups  \
18807                  Zygophyllum xanthoxylon  Eukaryota;Plants;Land Plants   
18808         Zygosaccharomyces mellis Y-12628   Eukaryota;Fungi;Ascomycetes   
18809  Zygosaccharomyces parabailii ATCC 60483   Eukaryota;Fungi;Ascomycetes   
18810       Zygotorulaspora mrakii NRRL Y-6702   Eukaryota;Fungi;Ascomycetes   
18811                     Zymoseptoria tritici   Eukaryota;Fungi;Ascomycetes   

       Size(Mb)      GC%           Type                     Replicons  CDS  \
18807  0.109577  33.7717    chloroplast        NC_052769.1/MT796492.1   69   
18808  0.024335  20.3123  mitochondrion        NC_036374.1/KU920675.1   14   
18809  0.029945  26.6088  mitochondrion                 MT:CP019506.1   13   
18810  0.037644  18.8184  mitochondrion  MT:NW_023500906.1/CP058612.1    0   
18811  0.043964  31.9352  mitochondrion        NC_010222.1/EU090238.1   22   

               Release Date  Genes  Pseudogene  
18807  2021-02-09T00:00:00Z    111           4  
18808  2017-12-18T00:00:00Z     40           0  
18809  2017-02-03T00:00:00Z     35           0  
18810  2020-10-28T00:00:00Z      0           0  
18811  2008-01-03T00:00:00Z     43           0  

Sprawdźmy, jaki jest typ obiektu, w którym zostały umieszczone dane:

# Typ obiektu dane
print(f'Typ obiektu dane: {type(dane)}')
Typ obiektu dane: <class 'pandas.core.frame.DataFrame'>

Nie powinno być zaskoczeniem, że otrzymaliśmy ramkę danych. Teraz sprawdźmy rozmiary ramki:

# Rozmiar ramki
print(f'Rozmiary ramki: {dane.shape}, rzędów: {dane.shape[0]}, kolumn: {dane.shape[1]}')
Rozmiary ramki: (18812, 10), rzędów: 18812, kolumn: 10

Atrybut columns pozwala pobrać nazwy kolumn:

# Nazwy kolumn
print(f'Kolumny: {dane.columns}')
Kolumny: Index(['Organism Name', 'Organism Groups', 'Size(Mb)', 'GC%', 'Type',
       'Replicons', 'CDS', 'Release Date', 'Genes', 'Pseudogene'],
      dtype='object')

Możemy też uzyskać dane na temat indeksów:

# Dane na temat indeksów
print(f'Indeksy: {dane.index}')
Indeksy: RangeIndex(start=0, stop=18812, step=1)

Typy danych przechowywanych w kolumnach można pobrać z atrybutu dtypes:

# Typy danych w kolumnach:
print(dane.dtypes)
Organism Name       object
Organism Groups     object
Size(Mb)           float64
GC%                float64
Type                object
Replicons           object
CDS                  int64
Release Date        object
Genes                int64
Pseudogene           int64
dtype: object

Liczebność kolumn każdego z typów pobieramy wywołując metodę value_counts():

# Liczebność kolumn określonych typów:
print(dane.dtypes.value_counts())
object     5
int64      3
float64    2
dtype: int64

Metoda info() także pokazuje powyższe informacje:

# Informacje o ramce:
print(dane.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 18812 entries, 0 to 18811
Data columns (total 10 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   Organism Name    18812 non-null  object 
 1   Organism Groups  18812 non-null  object 
 2   Size(Mb)         18812 non-null  float64
 3   GC%              18812 non-null  float64
 4   Type             18812 non-null  object 
 5   Replicons        18812 non-null  object 
 6   CDS              18812 non-null  int64  
 7   Release Date     18812 non-null  object 
 8   Genes            18812 non-null  int64  
 9   Pseudogene       18812 non-null  int64  
dtypes: float64(2), int64(3), object(5)
memory usage: 1.4+ MB
None

Podstawową statystykę danych przechowywanych w kolumnach możemy uzyskać używając metody describe():

print(dane.describe())
           Size(Mb)           GC%           CDS         Genes    Pseudogene
count  18812.000000  18812.000000  18812.000000  18812.000000  18812.000000
mean       0.074621     35.933209     39.307357     64.014671      0.520785
std        0.361654      7.864528     78.848303     87.199607      1.979815
min        0.001136      8.385160      0.000000      0.000000      0.000000
25%        0.016449     31.952150     13.000000     13.000000      0.000000
50%        0.017100     37.432350     13.000000     37.000000      0.000000
75%        0.151548     41.049400     83.000000    129.000000      0.000000
max       41.196000     68.015600   9230.000000   9230.000000     81.000000

Transpozycja może poprawić czytelność wyników:

print(dane.describe().T)
              count       mean        std       min        25%       50%  \
Size(Mb)    18812.0   0.074621   0.361654  0.001136   0.016449   0.01710   
GC%         18812.0  35.933209   7.864528  8.385160  31.952150  37.43235   
CDS         18812.0  39.307357  78.848303  0.000000  13.000000  13.00000   
Genes       18812.0  64.014671  87.199607  0.000000  13.000000  37.00000   
Pseudogene  18812.0   0.520785   1.979815  0.000000   0.000000   0.00000   

                   75%        max  
Size(Mb)      0.151548    41.1960  
GC%          41.049400    68.0156  
CDS          83.000000  9230.0000  
Genes       129.000000  9230.0000  
Pseudogene    0.000000    81.0000  

Metoda describe()przyjmuje argumenty, które pozwalają np. pobrać dane określonego typu.

print(dane.describe(include=object).T)
                 count unique                           top   freq
Organism Name    18812  18185         Plasmodium falciparum     27
Organism Groups  18812     19  Eukaryota;Plants;Land Plants   6227
Type             18812      7                 mitochondrion  12312
Replicons        18812  18807                  NC_016668.1/      2
Release Date     18812   1401          2020-04-26T00:00:00Z    310
  • Przy danych o wartościach typu int64 musimy zaimportować numpy.
import numpy as np
print(dane.describe(include=np.int64).T)
              count       mean        std  min   25%   50%    75%     max
CDS         18812.0  39.307357  78.848303  0.0  13.0  13.0   83.0  9230.0
Genes       18812.0  64.014671  87.199607  0.0  13.0  37.0  129.0  9230.0
Pseudogene  18812.0   0.520785   1.979815  0.0   0.0   0.0    0.0    81.0

Można podać kilka typów w formie listy, choć w podanym niżej przykładzie nie ma to większego sensu, ponieważ jak widać wyżej, dla danych liczbowych i typu object, są prezentowane inne wyniki:

print(dane.describe(include=[object,np.int64]).T)
                 count unique                           top   freq      mean  \
Organism Name    18812  18185         Plasmodium falciparum     27       NaN   
Organism Groups  18812     19  Eukaryota;Plants;Land Plants   6227       NaN   
Type             18812      7                 mitochondrion  12312       NaN   
Replicons        18812  18807                  NC_016668.1/      2       NaN   
CDS              18812    NaN                           NaN    NaN   39.3074   
Release Date     18812   1401          2020-04-26T00:00:00Z    310       NaN   
Genes            18812    NaN                           NaN    NaN   64.0147   
Pseudogene       18812    NaN                           NaN    NaN  0.520785   

                     std  min  25%  50%  75%   max  
Organism Name        NaN  NaN  NaN  NaN  NaN   NaN  
Organism Groups      NaN  NaN  NaN  NaN  NaN   NaN  
Type                 NaN  NaN  NaN  NaN  NaN   NaN  
Replicons            NaN  NaN  NaN  NaN  NaN   NaN  
CDS              78.8483    0   13   13   83  9230  
Release Date         NaN  NaN  NaN  NaN  NaN   NaN  
Genes            87.1996    0   13   37  129  9230  
Pseudogene       1.97982    0    0    0    0    81  

Jeśli potrzebujemy nadać etykiety indeksom wierszy, można to zrobić za pomocą metody set_index(), która zwraca zmienioną kopię ramki:

kopia = dane.set_index(['Organism Name'])
print(kopia.head(3))
                                       Organism Groups  Size(Mb)      GC%  \
Organism Name                                                               
Aacanthocnema dobsoni        Eukaryota;Animals;Insects  0.015179  21.9382   
Abacion magnum         Eukaryota;Animals;Other Animals  0.015160  33.4037   
Abalistes stellaris           Eukaryota;Animals;Fishes  0.016502  44.4189   

                                Type               Replicons  CDS  \
Organism Name                                                       
Aacanthocnema dobsoni  mitochondrion  NC_038132.1/MG989216.1   13   
Abacion magnum         mitochondrion  NC_021932.1/JX437062.1   13   
Abalistes stellaris    mitochondrion  NC_011943.1/AP009202.1   13   

                               Release Date  Genes  Pseudogene  
Organism Name                                                   
Aacanthocnema dobsoni  2018-07-31T00:00:00Z     37           0  
Abacion magnum         2013-08-06T00:00:00Z     35           0  
Abalistes stellaris    2009-01-22T00:00:00Z     13           0  

Jak widać, wartości z kolumny Organism Name stały się etykietami dla poszczególnych wierszy, a kolumna została usunięta. Można to zmienić ustawiając odpowiedni parametr:

kopia = dane.set_index(['Organism Name'], drop=False )
print(kopia.head(3))
                               Organism Name                  Organism Groups  \
Organism Name                                                                   
Aacanthocnema dobsoni  Aacanthocnema dobsoni        Eukaryota;Animals;Insects   
Abacion magnum                Abacion magnum  Eukaryota;Animals;Other Animals   
Abalistes stellaris      Abalistes stellaris         Eukaryota;Animals;Fishes   

                       Size(Mb)      GC%           Type  \
Organism Name                                             
Aacanthocnema dobsoni  0.015179  21.9382  mitochondrion   
Abacion magnum         0.015160  33.4037  mitochondrion   
Abalistes stellaris    0.016502  44.4189  mitochondrion   

                                    Replicons  CDS          Release Date  \
Organism Name                                                              
Aacanthocnema dobsoni  NC_038132.1/MG989216.1   13  2018-07-31T00:00:00Z   
Abacion magnum         NC_021932.1/JX437062.1   13  2013-08-06T00:00:00Z   
Abalistes stellaris    NC_011943.1/AP009202.1   13  2009-01-22T00:00:00Z   

                       Genes  Pseudogene  
Organism Name                             
Aacanthocnema dobsoni     37           0  
Abacion magnum            35           0  
Abalistes stellaris       13           0  

Odwrotne działanie, czyli przywrócenie kolumny z indeksu, przeprowadzamy z użyciem metody reset_index():

kopia = dane.set_index(['Organism Name'])
kopia_kopii = kopia.reset_index()
print(kopia_kopii.head())
           Organism Name                  Organism Groups  Size(Mb)      GC%  \
0  Aacanthocnema dobsoni        Eukaryota;Animals;Insects  0.015179  21.9382   
1         Abacion magnum  Eukaryota;Animals;Other Animals  0.015160  33.4037   
2    Abalistes stellaris         Eukaryota;Animals;Fishes  0.016502  44.4189   
3  Abax parallelepipedus        Eukaryota;Animals;Insects  0.017701  20.7446   
4        Abbottina binhi         Eukaryota;Animals;Fishes  0.016609  44.1387   

            Type               Replicons  CDS          Release Date  Genes  \
0  mitochondrion  NC_038132.1/MG989216.1   13  2018-07-31T00:00:00Z     37   
1  mitochondrion  NC_021932.1/JX437062.1   13  2013-08-06T00:00:00Z     35   
2  mitochondrion  NC_011943.1/AP009202.1   13  2009-01-22T00:00:00Z     13   
3  mitochondrion  NC_030592.1/KT876877.1   13  2016-07-12T00:00:00Z     37   
4  mitochondrion  NC_048988.1/MK852688.1   13  2020-06-28T00:00:00Z     37   

   Pseudogene  
0           0  
1           0  
2           0  
3           0  
4           0  

Selekcja danych i dalsza analiza

Popracujmy dalej z danymi, jeśli to potrzebne importując je:

import pandas as pd
# Wczytanie danych z pliku csv
dane = pd.read_csv('organelles.csv')

Pobierzmy dane dotyczące organelli dla których zostały opublikowane genomy:

organelle = dane['Type']
print(organelle)
0        mitochondrion
1        mitochondrion
2        mitochondrion
3        mitochondrion
4        mitochondrion
             ...      
18807      chloroplast
18808    mitochondrion
18809    mitochondrion
18810    mitochondrion
18811    mitochondrion
Name: Type, Length: 18812, dtype: object

Teraz znajdźmy wartości unikalne w kolumnie, pozwoli to sprawdzić dla jakich organelli mamy dane (albo raczej jak zostały opisane).

print(organelle.unique())
['mitochondrion' 'chloroplast' 'plastid' 'apicoplast' 'kinetoplast'
'cyanelle' 'chromatophore']

Sprawdźmy, ile jest poszczególnych wartości:

print(organelle.value_counts())
mitochondrion    12312
chloroplast       5379
plastid           1054
apicoplast          61
kinetoplast          3
chromatophore        2
cyanelle             1
Name: Type, dtype: int64

Metoda isin() pozwala na selekcję danych na podstawie przyrównania do elementów listy. Pobierzmy zatem dane dla plastydów i chloroplastów, aby uzyskać wszystkie dane dla plastydów (chloroplast to forma plastydu):

plastydy = dane[dane['Type'].isin(['chloroplast','plastid'])]
print(plastydy.describe())
          Size(Mb)          GC%          CDS        Genes   Pseudogene
count  6433.000000  6433.000000  6433.000000  6433.000000  6433.000000
mean      0.151713    36.992838    85.896782   130.748173     1.410539
std       0.028342     2.533923    23.787675    26.311608     2.849150
min       0.011348    20.462500     0.000000     0.000000     0.000000
25%       0.149227    36.492900    83.000000   129.000000     0.000000
50%       0.155021    37.350000    85.000000   131.000000     0.000000
75%       0.159230    38.131000    87.000000   133.000000     2.000000
max       1.352310    57.664000   863.000000   912.000000    40.000000

Obiekt zwracany przez metodę isin() to ramka danych, podobnie zresztą do obiektu zwracanego przez metodę describe(), co zresztą możemy łatwo sprawdzić:

plastydy_stat = plastydy.describe()
print(f'Typ zwracany przez isin()    : {type(plastydy)}')
print(f'Typ zwracany przez describe(): {type(plastydy_stat)}')
Typ zwracany przez isin()    : <class 'pandas.core.frame.DataFrame'>)
Typ zwracany przez describe(): <class 'pandas.core.frame.DataFrame'>)

Możemy zatem łatwo pobrać wybrane wartości, korzystając ze sposobów poznanych poprzednio:

print(f"Średnia długość genomu (Mb):            \
{round(plastydy_stat.loc['mean','Size(Mb)'], 2)}")
print(f"Wartość minimalna rozmiaru genomu (Mb): \
{round(plastydy_stat.loc['min','Size(Mb)'], 2)}")
print(f"Wartość maksymalna liczby genów:        \
{plastydy_stat.loc['max','Genes']}")
Średnia długość genomu (Mb):            0.15
Wartość minimalna rozmiaru genomu (Mb): 0.01
Wartość maksymalna liczby genów:        912.0

Sprawdźmy, dla jakich organizmów jest w bazie najwięcej danych:

organizmy = dane['Organism Name']
print(organizmy.value_counts().head(10))
Plasmodium falciparum     27
Homo sapiens              23
Enteromyxum leei           8
Solanum lycopersicum       8
Clathrina clathrus         6
Canis lupus familiaris     5
Glycine max                4
Rhododendron simsii        4
Chenopodium quinoa         4
Gossypium raimondii        4
Name: Organism Name, dtype: int64

Jak widać, najwięcej danych mamy dla Plasmodium falciparum, jest to zarodziec sierpowaty, wywołujący malarię. Ciekawe, dla jakich organelli, ile genomów zostało zbadanych:

zarodziec_sierpowaty = dane[dane['Organism Name'] == 'Plasmodium falciparum']
print(zarodziec_sierpowaty['Type'].value_counts())
mitochondrion    14
apicoplast       13
Name: Type, dtype: int64

Sprawdźmy teraz jakie właściwie grupy organizmów mamy w naszej ramce:

print(dane['Organism Groups'].unique())
['Eukaryota;Animals;Insects' 'Eukaryota;Animals;Other Animals'
 'Eukaryota;Animals;Fishes' 'Eukaryota;Plants;Land Plants'
 'Eukaryota;Animals;Reptiles' 'Eukaryota;Fungi;Other Fungi'
 'Eukaryota;Protists;Other Protists' 'Eukaryota;Animals;Birds'
 'Eukaryota;Other;Other' 'Eukaryota;Animals;Roundworms'
 'Eukaryota;Animals;Mammals' 'Eukaryota;Fungi;Ascomycetes'
 'Eukaryota;Fungi;Basidiomycetes' 'Eukaryota;Animals;Flatworms'
 'Eukaryota;Animals;Amphibians' 'Eukaryota;Plants;Green Algae'
 'Eukaryota;Protists;Apicomplexans' 'Eukaryota;Plants;Other Plants'
 'Eukaryota;Protists;Kinetoplasts']

Użyjemy teraz atrybutu str dostępnego dla obiektów Series. Posiada on przypisany obiekt StringMethod, który z kolei udostępnia metody przydatne do pracy z łańcuchami znaków. Część z nich odpowiada tym, które poznaliśmy w pierwszej części kursu przy omawianiu pracy z łańcuchami. Poniżej kilka przykładów:

grupy = dane['Organism Groups']
print(f'Typ: {type(grupy)}')
Typ: <class 'pandas.core.series.Series'>
print(grupy.str.upper().head())
0          EUKARYOTA;ANIMALS;INSECTS
1    EUKARYOTA;ANIMALS;OTHER ANIMALS
2           EUKARYOTA;ANIMALS;FISHES
3          EUKARYOTA;ANIMALS;INSECTS
4           EUKARYOTA;ANIMALS;FISHES
Name: Organism Groups, dtype: object
print(grupy.str.lower().head())
0          eukaryota;animals;insects
1    eukaryota;animals;other animals
2           eukaryota;animals;fishes
3          eukaryota;animals;insects
4           eukaryota;animals;fishes
Name: Organism Groups, dtype: object
print(grupy.str.replace('a','@').head())
0          Euk@ryot@;Anim@ls;Insects
1    Euk@ryot@;Anim@ls;Other Anim@ls
2           Euk@ryot@;Anim@ls;Fishes
3          Euk@ryot@;Anim@ls;Insects
4           Euk@ryot@;Anim@ls;Fishes
Name: Organism Groups, dtype: object
print(grupy.str.slice(4,8).head())
0    ryot
1    ryot
2    ryot
3    ryot
4    ryot
Name: Organism Groups, dtype: object

Metody contains() możemy użyć do selekcji danych na podstawie fragmentów łańcuchów znaków. Zwraca ona serię wartości boolowskich wskazujących na obecność szukanego ciągu znaków.

print(grupy.str.contains('Animals').head())
0    True
1    True
2    True
3    True
4    True
Name: Organism Groups, dtype: bool

Teraz pozostaje użyć jej do filtrowania danych:

poa = dane[dane['Organism Name'].str.contains('Poa')]
print(poa[['Organism Name', 'Type']])
        Organism Name         Type
13711     Poa alsodes  chloroplast
13712       Poa annua      plastid
13713    Poa interior      plastid
13714   Poa nemoralis      plastid
13715   Poa palustris      plastid
13716  Poa saltuensis  chloroplast
13717   Poa trivialis      plastid
13718      Poa wolfii  chloroplast

Gdybyśmy chcieli uzyskać dodatkową kolumnę zawierającą tylko nazwę rodzaju organizmów, na przykład w celu łatwiejszej analizy danych, możemy posłużyć się metoda split():

# Dzielimy ciąg znaków w kolumnie Organism Name po spacji 
# a następnie pobieramu pierwszy element powstałej listy
# i wpisujemy go do kolumny Rodzaj
dane['Rodzaj'] = dane['Organism Name'].str.split(' ').str[0]
print(dane[['Organism Name', 'Rodzaj']])
                                 Organism Name             Rodzaj
0                        Aacanthocnema dobsoni      Aacanthocnema
1                               Abacion magnum            Abacion
2                          Abalistes stellaris          Abalistes
3                        Abax parallelepipedus               Abax
4                              Abbottina binhi          Abbottina
...                                        ...                ...
18807                  Zygophyllum xanthoxylon        Zygophyllum
18808         Zygosaccharomyces mellis Y-12628  Zygosaccharomyces
18809  Zygosaccharomyces parabailii ATCC 60483  Zygosaccharomyces
18810       Zygotorulaspora mrakii NRRL Y-6702    Zygotorulaspora
18811                     Zymoseptoria tritici       Zymoseptoria

[18812 rows x 2 columns]

Wybierzmy ponownie dane dotyczące plastydów, ale tym razem tylko dla roślin telomowych (“Land Plants”).

plastydy = dane[dane['Type'].isin(['chloroplast','plastid']) \
                & dane['Organism Groups'].str.contains('Land Plants')]
print(plastydy[['Organism Name', 'Organism Groups', 'Type']].head())
              Organism Name               Organism Groups         Type
7          Abelia chinensis  Eukaryota;Plants;Land Plants  chloroplast
8          Abelia sanguinea  Eukaryota;Plants;Land Plants  chloroplast
9      Abelia x grandiflora  Eukaryota;Plants;Land Plants  chloroplast
10  Abeliophyllum distichum  Eukaryota;Plants;Land Plants  chloroplast
11   Abelmoschus esculentus  Eukaryota;Plants;Land Plants  chloroplast

Jak widać, użyliśmy operatora & (and) ale można oczywiście używać | (or) a także odwracać wynik filtrowania:

plastydy = dane[~dane['Type'].isin(['chloroplast','plastid']) \
                & ~dane['Organism Groups'].str.contains('Land Plants')]
print(plastydy[['Organism Name', 'Organism Groups', 'Type']].head())
           Organism Name                  Organism Groups           Type
0  Aacanthocnema dobsoni        Eukaryota;Animals;Insects  mitochondrion
1         Abacion magnum  Eukaryota;Animals;Other Animals  mitochondrion
2    Abalistes stellaris         Eukaryota;Animals;Fishes  mitochondrion
3  Abax parallelepipedus        Eukaryota;Animals;Insects  mitochondrion
4        Abbottina binhi         Eukaryota;Animals;Fishes  mitochondrion

Dane dotyczące czasu

Zaimportujmy ponownie dane (jeśli to konieczne).

import pandas as pd
# Wczytanie danych z pliku csv
dane = pd.read_csv('organelles.csv')

Sprawdźmy (ponownie) typ danych przechowywanych w każdej kolumnie:

print(dane.dtypes)
Organism Name       object
Organism Groups     object
Size(Mb)           float64
GC%                float64
Type                object
Replicons           object
CDS                  int64
Release Date        object
Genes                int64
Pseudogene           int64
dtype: object

Jak widać, dane określające czas upublicznienia genomów są zapisywane jako typ object. Dane dotyczące czasu, warto jednak przechowywać używając odpowiedniego typu danych, co umożliwia dokonywanie różnych operacji uwzględniając specyficzny charakter takich danych. Można to zrobić od razu przy imporcie danych z pliku:

import pandas as pd
# Wczytanie danych z pliku csv
dane = pd.read_csv('organelles.csv', parse_dates = ['Release Date'])
print(dane.dtypes)
Organism Name                   object
Organism Groups                 object
Size(Mb)                       float64
GC%                            float64
Type                            object
Replicons                       object
CDS                              int64
Release Date       datetime64[ns, UTC]
Genes                            int64
Pseudogene                       int64
dtype: object

Inną opcją jest zmiana typu istniejącej kolumny:

import pandas as pd
# Wczytanie danych z pliku csv
dane = pd.read_csv('organelles.csv')
dane['Release Date'] = pd.to_datetime(dane['Release Date'])
print(dane.dtypes)
Organism Name                   object
Organism Groups                 object
Size(Mb)                       float64
GC%                            float64
Type                            object
Replicons                       object
CDS                              int64
Release Date       datetime64[ns, UTC]
Genes                            int64
Pseudogene                       int64
dtype: object

Od razu możemy zauważyć, że zmienił się sposób wyświetlania danych w kolumnie.

print(dane['Release Date'].head(3))
0   2018-07-31 00:00:00+00:00
1   2013-08-06 00:00:00+00:00
2   2009-01-22 00:00:00+00:00
Name: Release Date, dtype: datetime64[ns, UTC]

Poszczególne składowe można uzyskać z odpowiednich atrybutów:

# Rok
print(dane['Release Date'].dt.year.head(3))
0    2018
1    2013
2    2009
Name: Release Date, dtype: int64
# Miesiąc
print(dane['Release Date'].dt.month.head(3))
0    7
1    8
2    1
Name: Release Date, dtype: int64
# Dzień
print(dane['Release Date'].dt.day.head(3))
0    31
1     6
2    22
Name: Release Date, dtype: int64
# Godzina
print(dane['Release Date'].dt.hour.head(3))
0    0
1    0
2    0
Name: Release Date, dtype: int64

Co prawda nie jest to widoczne wprost w danych, ale można także uzyskać informację, jaki dzień tygodnia odpowiada danej dacie. Może ona zostać przedstawiona w formie cyfry (0 - poniedziałek, 1 - wtorek itd.), lub jako angielska nazwa dnia tygodnia:

# Dzień tygodnia - cyfry
print(dane['Release Date'].dt.dayofweek.head(3))
0    1
1    1
2    3
Name: Release Date, dtype: int64
# Dzień tygodnia - nazwy
print(dane['Release Date'].dt.day_name().head(3))
0     Tuesday
1     Tuesday
2    Thursday
Name: Release Date, dtype: object

Możemy teraz np. pobrać dane które ukazały się od początku 2021 r.

nowe = dane[dane['Release Date'].dt.year >= 2021].copy()
print(nowe[['Organism Name', 'Release Date']].head(5))
print('...')
print(f'Od początku 2021 ukazało się {nowe.shape[0]} genomów.')
                Organism Name              Release Date
12        Abelmoschus manihot 2021-03-09 00:00:00+00:00
13      Abelmoschus moschatus 2021-03-09 00:00:00+00:00
14  Abelmoschus sagittifolius 2021-03-09 00:00:00+00:00
33       Abraximorpha davidii 2021-03-26 00:00:00+00:00
43       Abutilon theophrasti 2021-03-26 00:00:00+00:00
...
Od początku 2021 ukazało się 989 genomów.

Przy okazji możemy zreindeksować ramkę. Ustawienie parametru drop = True nie dopuszcza do utworzenia kolumny z poprzednimi indeksami, inplace = True modyfikuje bezpośrednio ramkę.

nowe.reset_index(drop = True, inplace = True)
print(nowe[['Organism Name', 'Release Date']])
                 Organism Name              Release Date
0          Abelmoschus manihot 2021-03-09 00:00:00+00:00
1        Abelmoschus moschatus 2021-03-09 00:00:00+00:00
2    Abelmoschus sagittifolius 2021-03-09 00:00:00+00:00
3         Abraximorpha davidii 2021-03-26 00:00:00+00:00
4         Abutilon theophrasti 2021-03-26 00:00:00+00:00
..                         ...                       ...
984     Zonotrichia albicollis 2021-03-08 00:00:00+00:00
985            Zoysia matrella 2021-03-26 00:00:00+00:00
986           Zyginella minuta 2021-02-09 00:00:00+00:00
987         Zygophyllum fabago 2021-02-09 00:00:00+00:00
988    Zygophyllum xanthoxylon 2021-02-09 00:00:00+00:00

[989 rows x 2 columns]

Sprawdźmy jeszcze dane dla mitochondriów:

nowe = dane[(dane['Release Date'].dt.year >= 2021) \
            & (dane['Type'] == 'mitochondrion')]
nowe.reset_index(drop = True, inplace = True)
print(nowe[['Organism Name', 'Release Date', 'Type']].head(5))
print('...')
print(f'Od początku 2021 ukazało się {nowe.shape[0]} genomów mitochondriów.')
             Organism Name              Release Date           Type
0     Abraximorpha davidii 2021-03-26 00:00:00+00:00  mitochondrion
1     Acanthisitta chloris 2021-02-17 00:00:00+00:00  mitochondrion
2        Acidiella diversa 2021-03-26 00:00:00+00:00  mitochondrion
3  Acroneuria carolinensis 2021-03-26 00:00:00+00:00  mitochondrion
4       Acropteris iphiata 2021-03-26 00:00:00+00:00  mitochondrion
...
Od początku 2021 ukazało się 557 genomów mitochondriów.

Łatwo można uzyskać bieżący czas, zostanie zwrócony obiekt typu Timestamp, z którego można pobrać różne informacje dotyczące czasu, np:

teraz = pd.Timestamp.now()
print(f'Typ obiektu:  {type(teraz)}')
print(f'Data i czas:  {teraz}')
print(f'Data:         {teraz.date()}')
print(f'Czas:         {teraz.time()}')
print(f'Godzina:      {teraz.hour}')
print(f'Dzień w roku: {teraz.dayofyear}')
print(f'Tydzień:      {teraz.week}')
Typ obiektu:  <class 'pandas._libs.tslibs.timestamps.Timestamp'>
Data i czas:  2021-03-31 11:18:01.491502
Data:         2021-03-31
Czas:         11:18:01.491502
Godzina:      11
Dzień w roku: 90
Tydzień:      13

Operacje grupowania groupby

Operacje groupby są bardzo pomocne w analizie danych, umożliwiają stosunkowo łatwe łączenie, transformację oraz filtrowanie danych. Proces ten przebiega wg. schematu: ,,dziel-zastosuj-połącz’’ (ang. split-apply-combine). Możemy zatem wyróżnić trzy etapy:

  1. Dane zostają podzielone (split) na podstawie jednego lub więcej kluczy, mogą to być np. nazwy kolumny w ramce danych.
  2. Poszczególne części danych są przetwarzane za pomocą funkcji (apply)
  3. Wyniki są łączone (combine) w nowy zestaw danych.

Zobaczmy na kilku przykładach co można w ten sposób uzyskać, choć oczywiście będzie to jedynie wycinek możliwości operacji groupby.

Jeśli to konieczne, odczytajmy dane z pliku:

import pandas as pd
dane = pd.read_csv('organelles.csv')

Teraz zastosujmy operację grouby z użyciem nazwy kolumny Type jako klucza grupującego:

organelle = dane.groupby('Type')

Sprawdźmy jaki typ obiektu zwróciła metoda groupby() i spróbujmy użyć na nim funkcji print():

print(f'Typ obiektu:{type(organelle)}')
print(organelle)
Typ obiektu:<class 'pandas.core.groupby.generic.DataFrameGroupBy'>
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f6f50a64040>

Jak widać, otrzymany obiekt jest typu DataFrameGroupBy. Zastosowanie print() nie wyświetliło nam żadnych danych. Spróbujmy zatem wywołać jakąś funkcję na obiekcie:

rozmiar = organelle.size()
print(f'Typ: {type(rozmiar)}')
print(rozmiar)
Typ: <class 'pandas.core.series.Series'>
Type
apicoplast          61
chloroplast       5379
chromatophore        2
cyanelle             1
kinetoplast          3
mitochondrion    12312
plastid           1054
dtype: int64

Dzięki groupby mogliśmy pogrupować dane wg. rodzaju organelli, metoda size() umożliwiła policzenie liczby elementów w każdej kategorii i zwróciła obiekt Series. Wywołajmy teraz metodę describe():

opis = organelle.describe()
print(f'Typ: {type(opis)}')
print(opis)
Typ: <class 'pandas.core.frame.DataFrame'>
              Size(Mb)                                                    \
                 count      mean       std       min       25%       50%   
Type                                                                       
apicoplast        61.0  0.034207  0.007766  0.012928  0.029401  0.034242   
chloroplast     5379.0  0.152199  0.026511  0.015553  0.150469  0.155099   
chromatophore      2.0  0.999409  0.031410  0.977199  0.988304  0.999409   
cyanelle           1.0  0.135599       NaN  0.135599  0.135599  0.135599   
kinetoplast        3.0  0.030547  0.009995  0.020992  0.025355  0.029717   
mitochondrion  12312.0  0.034396  0.441088  0.001136  0.015848  0.016574   
plastid         1054.0  0.149232  0.036191  0.011348  0.137826  0.154570   

                                        GC%             ...  Genes          \
                    75%        max    count       mean  ...    75%     max   
Type                                                    ...                  
apicoplast     0.035107   0.053268     61.0  15.739062  ...   57.0    70.0   
chloroplast    0.159234   1.352310   5379.0  37.035624  ...  133.0   315.0   
chromatophore  1.010515   1.021620      2.0  38.944250  ...  911.5   922.0   
cyanelle       0.135599   0.135599      1.0  30.467800  ...  192.0   192.0   
kinetoplast    0.035324   0.040931      3.0  21.584733  ...   11.5    23.0   
mitochondrion  0.017014  41.196000  12312.0  35.483058  ...   37.0  9230.0   
plastid        0.159139   0.977190   1054.0  36.774486  ...  133.0   912.0   

              Pseudogene                                                  
                   count      mean       std  min   25%  50%   75%   max  
Type                                                                      
apicoplast          61.0  0.229508  0.588598  0.0  0.00  0.0  0.00   3.0  
chloroplast       5379.0  1.333705  2.560317  0.0  0.00  0.0  2.00  40.0  
chromatophore        2.0  4.500000  4.949747  1.0  2.75  4.5  6.25   8.0  
cyanelle             1.0  0.000000       NaN  0.0  0.00  0.0  0.00   0.0  
kinetoplast          3.0  0.000000  0.000000  0.0  0.00  0.0  0.00   0.0  
mitochondrion    12312.0  0.056855  1.054682  0.0  0.00  0.0  0.00  81.0  
plastid           1054.0  1.802657  3.990129  0.0  0.00  0.0  2.00  38.0  

[7 rows x 40 columns]

Otrzymaliśmy ramkę danych i opisowe statystyki dla poszczególnych organelli.

Ograniczmy wyniki dla kolumny Size(Mb):

print(organelle.describe()['Size(Mb)'])
                 count      mean       std       min       25%       50%  \
Type                                                                       
apicoplast        61.0  0.034207  0.007766  0.012928  0.029401  0.034242   
chloroplast     5379.0  0.152199  0.026511  0.015553  0.150469  0.155099   
chromatophore      2.0  0.999409  0.031410  0.977199  0.988304  0.999409   
cyanelle           1.0  0.135599       NaN  0.135599  0.135599  0.135599   
kinetoplast        3.0  0.030547  0.009995  0.020992  0.025355  0.029717   
mitochondrion  12312.0  0.034396  0.441088  0.001136  0.015848  0.016574   
plastid         1054.0  0.149232  0.036191  0.011348  0.137826  0.154570   

                    75%        max  
Type                                
apicoplast     0.035107   0.053268  
chloroplast    0.159234   1.352310  
chromatophore  1.010515   1.021620  
cyanelle       0.135599   0.135599  
kinetoplast    0.035324   0.040931  
mitochondrion  0.017014  41.196000  
plastid        0.159139   0.977190  

Teraz sprawdźmy średnią dla rozmiaru genomów:

print(organelle['Size(Mb)'].mean())
Type
apicoplast       0.034207
chloroplast      0.152199
chromatophore    0.999409
cyanelle         0.135599
kinetoplast      0.030547
mitochondrion    0.034396
plastid          0.149232
Name: Size(Mb), dtype: float64

Teraz użyjemy dwu kluczy, dla kolumn: Organism Groups oraz Type:

organizmy_organelle = dane.groupby(['Organism Groups', 'Type'])

Uzyskajmy średnią wielkość genomu dla każdej grupy organizmów, dla każdego typu organelli:

print(organizmy_organelle['Size(Mb)'].mean())
Organism Groups                    Type         
Eukaryota;Animals;Amphibians       mitochondrion    0.017533
Eukaryota;Animals;Birds            mitochondrion    0.017124
Eukaryota;Animals;Fishes           mitochondrion    0.016685
Eukaryota;Animals;Flatworms        mitochondrion    0.014463
Eukaryota;Animals;Insects          mitochondrion    0.015746
Eukaryota;Animals;Mammals          mitochondrion    0.016582
Eukaryota;Animals;Other Animals    mitochondrion    0.016340
Eukaryota;Animals;Reptiles         mitochondrion    0.017124
Eukaryota;Animals;Roundworms       mitochondrion    0.014594
Eukaryota;Fungi;Ascomycetes        mitochondrion    0.064716
Eukaryota;Fungi;Basidiomycetes     mitochondrion    0.078151
Eukaryota;Fungi;Other Fungi        mitochondrion    0.059099
Eukaryota;Other;Other              chloroplast      0.161175
                                   mitochondrion    0.032238
                                   plastid          0.172766
Eukaryota;Plants;Green Algae       chloroplast      0.156876
                                   mitochondrion    0.055061
                                   plastid          0.141459
Eukaryota;Plants;Land Plants       chloroplast      0.152268
                                   mitochondrion    0.413925
                                   plastid          0.148032
Eukaryota;Plants;Other Plants      chloroplast      0.153641
                                   mitochondrion    0.102788
Eukaryota;Protists;Apicomplexans   apicoplast       0.034207
                                   mitochondrion    0.006191
Eukaryota;Protists;Kinetoplasts    kinetoplast      0.030547
                                   mitochondrion    0.050477
Eukaryota;Protists;Other Protists  chloroplast      0.106175
                                   chromatophore    0.999409
                                   cyanelle         0.135599
                                   mitochondrion    0.599552
                                   plastid          0.142994
Name: Size(Mb), dtype: float64

Odwróćmy teraz kolejność podanych kluczy grupowania:

organizmy_organelle = dane.groupby(['Type', 'Organism Groups'])
print(organizmy_organelle['Size(Mb)'].mean())
Type           Organism Groups                  
apicoplast     Eukaryota;Protists;Apicomplexans     0.034207
chloroplast    Eukaryota;Other;Other                0.161175
               Eukaryota;Plants;Green Algae         0.156876
               Eukaryota;Plants;Land Plants         0.152268
               Eukaryota;Plants;Other Plants        0.153641
               Eukaryota;Protists;Other Protists    0.106175
chromatophore  Eukaryota;Protists;Other Protists    0.999409
cyanelle       Eukaryota;Protists;Other Protists    0.135599
kinetoplast    Eukaryota;Protists;Kinetoplasts      0.030547
mitochondrion  Eukaryota;Animals;Amphibians         0.017533
               Eukaryota;Animals;Birds              0.017124
               Eukaryota;Animals;Fishes             0.016685
               Eukaryota;Animals;Flatworms          0.014463
               Eukaryota;Animals;Insects            0.015746
               Eukaryota;Animals;Mammals            0.016582
               Eukaryota;Animals;Other Animals      0.016340
               Eukaryota;Animals;Reptiles           0.017124
               Eukaryota;Animals;Roundworms         0.014594
               Eukaryota;Fungi;Ascomycetes          0.064716
               Eukaryota;Fungi;Basidiomycetes       0.078151
               Eukaryota;Fungi;Other Fungi          0.059099
               Eukaryota;Other;Other                0.032238
               Eukaryota;Plants;Green Algae         0.055061
               Eukaryota;Plants;Land Plants         0.413925
               Eukaryota;Plants;Other Plants        0.102788
               Eukaryota;Protists;Apicomplexans     0.006191
               Eukaryota;Protists;Kinetoplasts      0.050477
               Eukaryota;Protists;Other Protists    0.599552
plastid        Eukaryota;Other;Other                0.172766
               Eukaryota;Plants;Green Algae         0.141459
               Eukaryota;Plants;Land Plants         0.148032
               Eukaryota;Protists;Other Protists    0.142994
Name: Size(Mb), dtype: float64

W uzyskanej w ten sposób, czyli z użyciem więcej niż jednej kolumn w celu grupowania, ramce danych mamy do czynienia z indeksem hierarchicznym. Zauważ jak wyświetlają się dane w ramce;

wynik = organizmy_organelle[['Size(Mb)', 'Genes']].mean()
print(wynik.head())
                                              Size(Mb)       Genes
Type        Organism Groups                                       
apicoplast  Eukaryota;Protists;Apicomplexans  0.034207   31.901639
chloroplast Eukaryota;Other;Other             0.161175  210.984848
            Eukaryota;Plants;Green Algae      0.156876  107.534591
            Eukaryota;Plants;Land Plants      0.152268  128.742328
            Eukaryota;Plants;Other Plants     0.153641  136.700000

Size(Mb) i Genes są tu kolumnami, natomiast Type oraz Organism Groups opisują indeksy:

print(wynik.index)
MultiIndex([(   'apicoplast',  'Eukaryota;Protists;Apicomplexans'),
            (  'chloroplast',             'Eukaryota;Other;Other'),
            (  'chloroplast',      'Eukaryota;Plants;Green Algae'),
            (  'chloroplast',      'Eukaryota;Plants;Land Plants'),
            (  'chloroplast',     'Eukaryota;Plants;Other Plants'),
            (  'chloroplast', 'Eukaryota;Protists;Other Protists'),
            ('chromatophore', 'Eukaryota;Protists;Other Protists'),
            (     'cyanelle', 'Eukaryota;Protists;Other Protists'),
            (  'kinetoplast',   'Eukaryota;Protists;Kinetoplasts'),
            ('mitochondrion',      'Eukaryota;Animals;Amphibians'),
            ('mitochondrion',           'Eukaryota;Animals;Birds'),
            ('mitochondrion',          'Eukaryota;Animals;Fishes'),
            ('mitochondrion',       'Eukaryota;Animals;Flatworms'),
            ('mitochondrion',         'Eukaryota;Animals;Insects'),
            ('mitochondrion',         'Eukaryota;Animals;Mammals'),
            ('mitochondrion',   'Eukaryota;Animals;Other Animals'),
            ...   
            (      'plastid', 'Eukaryota;Protists;Other Protists')],
           names=['Type', 'Organism Groups'])

Możemy zatem odwoływać się kolejno do etykiet indeksów, używając np. loc tak aby wybrać interesujące nas dane:

print(wynik.loc['mitochondrion'].loc[['Eukaryota;Animals;Insects', 'Eukaryota;Animals;Mammals']]\
      [['Genes','Size(Mb)']])
                               Genes  Size(Mb)
Organism Groups                               
Eukaryota;Animals;Insects  29.848341  0.015746
Eukaryota;Animals;Mammals  23.732194  0.016582

Oczywiście grupowanie można łączyć z odpowiednimi funkcjami pozwalającym na selekcję danych. Przykładowo, uzyskajmy dane dla organelli w grupie organizmów ‘Land Plants’ (rośliny telomowe) i wyświetlmy wybrane kolumny statystyk dla rozmiaru genomu (Size(Mb)).

rosliny = dane[dane['Organism Groups'].str.contains('Land Plants')]\
              .groupby('Type')
print(rosliny.describe()['Size(Mb)'][['count', 'mean', 'min', 'max']])
                count      mean       min       max
Type                                               
chloroplast    5018.0  0.152268  0.015553  0.707276
mitochondrion   260.0  0.413925  0.011640  1.999600
plastid         949.0  0.148032  0.011348  0.230012

Odczyt i zapis danych do plików w różnych formatach

Dotychczas odczytywaliśmy dane w formacie csv (ang. comma-separated values), w którym (domyślnie) separatorem jest przecinek:

import pandas as pd
dane = pd.read_csv('organelles.csv')

Dane zostały zapisane w ramce danych. Podczas większości operacji opisanych powyżej, dotyczących selekcji, modyfikacji, czy innych operacji na danych, także otrzymywaliśmy ramki z danymi. Można je także zapisać do pliku csv:

rosliny = dane[dane['Organism Groups'].str.contains('Land Plants')]\
              .groupby('Type')
wynik = rosliny.describe()['Size(Mb)'][['count', 'mean', 'min', 'max']]
print(wynik)
wynik.to_csv('rosliny_ladowe_rozmiar_genomu.csv')
                count      mean       min       max
Type                                               
chloroplast    5018.0  0.152268  0.015553  0.707276
mitochondrion   260.0  0.413925  0.011640  1.999600
plastid         949.0  0.148032  0.011348  0.230012

Możesz otworzyć plik w edytorze tekstu, lub np. w LibreOffice. Zauważ, że etykiety indeksów zostały zapisane w oddzielnej kolumnie. Domyślny separator można zmienić np. na tabulator, wtedy warto by jednak zmienić przedłużenie pliku na tsv (ang. tab-separated values):

wynik.to_csv('rosliny_ladowe_rozmiar_genomu.tsv', sep = '\t')

Odczytać plik w formacie tsv, można używając metody read_csv() z podaniem odpowiedniej opcji, lub metody read_table(), dla której tabulator jest separatorem domyślnym:

ramka_1 = pd.read_csv('rosliny_ladowe_rozmiar_genomu.tsv', sep = '\t')
print(ramka_1)
            Type   count      mean       min       max
0    chloroplast  5018.0  0.152268  0.015553  0.707276
1  mitochondrion   260.0  0.413925  0.011640  1.999600
2        plastid   949.0  0.148032  0.011348  0.230012
ramka_2 = pd.read_table('rosliny_ladowe_rozmiar_genomu.tsv')
print(ramka_2)
            Type   count      mean       min       max
0    chloroplast  5018.0  0.152268  0.015553  0.707276
1  mitochondrion   260.0  0.413925  0.011640  1.999600
2        plastid   949.0  0.148032  0.011348  0.230012

Dane można także zapisać w wielu innych formatach, np.:

# Format programu Excel
wynik.to_excel('rosliny_ladowe_rozmiar_genomu.xlsx')
# Format HTML
wynik.to_html('rosliny_ladowe_rozmiar_genomu.html')
# Format LaTeX
wynik.to_latex('rosliny_ladowe_rozmiar_genomu.latex')
# Format JSON
wynik.to_json('rosliny_ladowe_rozmiar_genomu.json')

Istnieje też możliwość odczytu wielu formatów (choć rezultaty mogą się różnić), np.:

# Format programu Excel
wynik_xlsx = pd.read_excel('rosliny_ladowe_rozmiar_genomu.xlsx')
print(f'xlsx:\n{wynik_xlsx}')
# Format HTML
wynik_html = pd.read_html('rosliny_ladowe_rozmiar_genomu.html')
print(f'html:\n{wynik_html}')
# Format JSON
wynik_json = pd.read_json('rosliny_ladowe_rozmiar_genomu.json')
print(f'json:\n{wynik_json}')
xlsx:
            Type  count      mean       min       max
0    chloroplast   5018  0.152268  0.015553  0.707276
1  mitochondrion    260  0.413925  0.011640  1.999600
2        plastid    949  0.148032  0.011348  0.230012
html:
[  Unnamed: 0_level_0              count               mean                min  \
                Type Unnamed: 1_level_1 Unnamed: 2_level_1 Unnamed: 3_level_1   
0        chloroplast             5018.0           0.152268           0.015553   
1      mitochondrion              260.0           0.413925           0.011640   
2            plastid              949.0           0.148032           0.011348   

                 max  
  Unnamed: 4_level_1  
0           0.707276  
1           1.999600  
2           0.230012  ]
json:
               count      mean       min       max
chloroplast     5018  0.152268  0.015553  0.707276
mitochondrion    260  0.413925  0.011640  1.999600
plastid          949  0.148032  0.011348  0.230012

Jeśli plik w formacie xlsx zawiera wiele arkuszy, powinniśmy wskazać ten, który chcemy zaimportować ustawiając parametr sheet_name="Nazwa Arkusza". W przeciwnym razie wczytany zostanie pierwszy arkusz.

Pobierz plik pomiary.xlsx i zapisz w miejscu, w którym uruchamiasz kod (lub zmodyfikuj ścieżkę do pliku) Następnie wczytaj go:

# Bez ustawienia arkusza
wynik_xlsx = pd.read_excel('pomiary.xlsx')
print(f'Arkusz domyślny:\n{wynik_xlsx}')
# Z ustawieniem arkusza
wynik_xlsx = pd.read_excel('pomiary.xlsx', sheet_name = 'szerokosci')
print(f'Wskazany arkusz:\n{wynik_xlsx}')
Arkusz domyślny:
  osobnik  długość
0       A     12.3
1       B     22.1
2       C     14.4
3       D     11.0
4       E     19.4
5       F     17.5
6       G     12.1
7       H     15.5
Wskazany arkusz:
  osobnik  szerokość
0       A        4.1
1       B        7.2
2       C        4.8
3       D        3.5
4       E        6.6
5       F        5.6
6       G        4.1
7       H        5.0

Zadanie

Uzyskaj średnie liczby genów i CDS w mitochondriach dla zwierząt, grzybów i roślin, tak aby wyświetlały się w ten sposób:

             Genes        CDS
Grupy                        
Animals  25.926091  12.628505
Fungi    34.237454  15.784578
Plants   71.170270  44.562162

Zapisz wynik w pliku o formacie tsv

Przykładowe rozwiązanie

import pandas as pd
dane = pd.read_csv('http://ggoralski.pl/files/inne/organelles.csv')
#dane = pd.read_csv('organelles.csv')
# Tworzymy kolumnę dla poszczególnych grup organizmów
dane['Grupy'] = dane['Organism Groups'].str.split(';').str[1]
# Operacja groupby
wynik_1 = dane.groupby(['Type', 'Grupy'])
# Obliczamy średnie
wynik_2 = wynik_1[['Genes', 'CDS']].mean()
# Selekcja danych dla mitochondriów i grup organizmów:
wynik_3 = wynik_2.loc['mitochondrion'].loc[['Animals','Fungi','Plants']]
print(wynik_3)
wynik_3.to_csv('mitochondria.tsv', sep = '\t')
Last updated on 3 Apr 2024
Published on 3 Apr 2024