Pandas
Obiective
Să înțelegeți care e diferența dintre Numpy și Pandas.
Să știți cum să utilizați funcțiile din Pandas și metodele claselor pandas.Series, și pandas.DataFrame.
Să înțelegeți conceptele statistice - std, Q1,Q2,Q3.
Să știți cum să utilizați metodele de selectare din Pandas.
Să fiți capabile să curățiți o bază de date.
Să știți cum să modelați datele.
import matplotlib.pyplot as plt
import numpy as np
Pandas 🐼
De ce Pandas?
Am văzut mai devreme că librăria Numpy ne oferă libertatea de a lucra mai ușor cu mai multe dimensiuni decât listele de liste. Cu ajutorul oparțiilor vectorizate putem mai rapid și mai ușor să transformăm datele decât folosind loop-ul for
.
Totuși Numpy are câteva limitări:
Numpy nu oferă posibilitatea de a avea denumirile de coloane
Numpy permite de a avea doar un singur tip de date într-un array
Nu conține metode gata facute(pre-built) care să faciliteze procesul de analiză a datelor.
Limitările de mai sus sunt rezolvate de Pandas. Pandas nu este o ”înlocuire” a librăriei Numpy, ci mai degrabă e o extensie a lui Numpy. Codul din spatele funcțiilor și metodelor din Pandas se bazează pe libraria Numpy astfel multe din conceptele anterior învățate le vom regăsi și aici.
Import pandas
import pandas as pd
Pandas are 2 clase principale: pandas.Series și pandas.DataFrame.
Care este diferența dintre aceste două clase?
Pandas.DataFrame
DataFrame-ul e o structură primară a librăriei Pandas, bi-dimensională și heterogenă.
Putem să construim un DataFrame utilizând o listă de liste sau un array.
pd.DataFrame(np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]))
0
1
2
3
0
1
2
3
4
1
5
6
7
8
2
9
10
11
12
Putem să utilizăm un dicționar în crearea unui DataFrame.
pd.DataFrame({'a':[1,2,3,4], 'b':[5,6,7,8], 'c':[9,10,11,12]})
a
b
c
0
1
5
9
1
2
6
10
2
3
7
11
3
4
8
12
Clasa DataFrame are și un parametru cu care putem să specificăm numele coloanelor într-o listă. De data asta atribuim DataFrame-ul unei variabile.
df = pd.DataFrame([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]], columns = ['a', 'b', 'c', 'd'])
df
a
b
c
d
0
1
2
3
4
1
5
6
7
8
2
9
10
11
12
Ce diferență este între primul, al doilea și al treilea tabel?
# Creați un DataFrame cu 3 coloane și 2 rânduri, iar coloanele să aibă nume
df1 = pd.DataFrame({'a' : [1, 2], 'b': [3, 4], 'c':[5,6]})
df1
a
b
c
0
1
3
5
1
2
4
6
Pandas.Series
Obiectul Series este un ndarray cu o singură dimensiune.
Ca să instanțiem un obiect Series putem folosi o listă de valori.
pd.Series([1, 2, 3, 4])
0 1
1 2
2 3
3 4
dtype: int64
Obiectul Series poate avea și un nume.
pd.Series([1, 2, 3, 4], name = 'numbers')
0 1
1 2
2 3
3 4
Name: numbers, dtype: int64
Un obiect Series poate fi și sintaxa de mai jos. Ce reprezintă sintaxa de mai jos?
df['a']
0 1
1 5
2 9
Name: a, dtype: int64
Sintaxa de mai sus reprezintă cea mai simplă modalitate de a selecta o coloană dintr-un DataFrame.
# selectează coloana 'd' din tabelul df
df['d']
0 4
1 8
2 12
Name: d, dtype: int64
Documentație:
Elementele unui DataFrame
Cum convertim din Pandas in Numpy?
df = pd.DataFrame([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]], columns = ['a', 'b', 'c', 'd'])
df
a
b
c
d
0
1
2
3
4
1
5
6
7
8
2
9
10
11
12
Metoda to_numpy()
a clasei DataFrame convertește un obiect DataFrame într-un array.
df.to_numpy()
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
Citirea unui fișier CSV cu Pandas
Pentru a accesa un set de date, putem să folosim funcția read_csv() care primește ca argument path-ul, sau ”calea” spre fișierul CSV.
Această funcție ne returnează un DataFrame.
Documentație: pandas.read_csv()
books = pd.read_csv('https://girlsgoitpublic.z6.web.core.windows.net/books_to_be_cleaned.csv')
Metoda head(), aparține clasei DataFrame. Această metodă ne permite să vizualizăm implicit primele 5 rânduri din tabel.
Însă putem să vizualizăm și mai multe rânduri dacă specificăm acest parametru.
# indică argumentul 10 in funcția head() și execută programul
# ce observi? dar daca scrii -5?
books.head()
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
Metoda tail() este opusul metodei head().
books.tail()
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
195
17899948
Rebecca
Daphne du Maurier
328317
4.23
430751
22157
449p
2013
Classics
196
32261
Tess of the D'Urbervilles
Thomas Hardy
88562
3.80
233821
8491
518p
2003
Classics
197
7126
The Count of Monte Cristo
Alexandre Dumas
116688
4.25
731027
20622
1276p
2003
Classics
198
17245
Dracula
Bram Stoker
636610
4.00
907768
24683
488p
1986
Classics
199
662
Atlas Shrugged
Ayn Rand
247445
3.69
348149
17053
1168p
1999
Classics
Cum salvăm un DataFrame într-un fișier CSV?
Metoda to_csv()
returnează un fișier CSV. Această metodă primește ca parametri numele fișierului. De asemenea specificăm parametrul index
cu valoarea False
ca să nu anuleze indexul exitent din DataFrame transformându-l într-o coloană și să indexeseze din nou rândurile.
df.to_csv('df.csv', index=False)
Atribute
Aceste atribute ne ajută să investigăm DataFrame-ului.
Atributul columns
ne returnează o listă cu numele coloanelor din tabel.
books.columns
Index(['Id', 'Name', 'Authour', 'Score', 'Rating', 'Rating Count',
'Review Count', 'Page Count', 'Year', 'Genres'],
dtype='object')
Atributul dtypes
ne ajută să investigăm ce tipuri de date avem în tabel.
books.dtypes
Id int64
Name object
Authour object
Score int64
Rating float64
Rating Count int64
Review Count int64
Page Count object
Year int64
Genres object
dtype: object
Atributul index
ne returnează intervalul de indecși conținut de DataFrame-ul books
.
books.index
RangeIndex(start=0, stop=200, step=1)
Atributul shape ne returnează un tuplu care conține numărul de rânduri și numărul de coloane.
books.shape
(200, 10)
# selecteaza numărul de rânduri din tabelul books cu ajutorul atributului shape
books.shape[0]
200
Metode
Metode de investigare a DataFrame-ului
books.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 200 entries, 0 to 199
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Id 200 non-null int64
1 Name 200 non-null object
2 Authour 200 non-null object
3 Score 200 non-null int64
4 Rating 191 non-null float64
5 Rating Count 200 non-null int64
6 Review Count 200 non-null int64
7 Page Count 200 non-null object
8 Year 200 non-null int64
9 Genres 186 non-null object
dtypes: float64(1), int64(5), object(4)
memory usage: 15.8+ KB
# Ce informație ne oferă metoda info()?
Metoda describe()
ne oferă informații statistice despre toate coloanele numerice.
books.describe()
Id
Score
Rating
Rating Count
Review Count
Year
count
2.000000e+02
2.000000e+02
191.000000
2.000000e+02
200.000000
200.000000
mean
4.031287e+06
3.704144e+05
4.111152
1.001351e+06
28013.625000
2002.105000
std
1.050539e+07
4.211493e+05
0.234172
1.002018e+06
25818.271576
9.026147
min
1.000000e+00
7.125500e+04
3.410000
8.387000e+03
131.000000
1963.000000
25%
5.123500e+03
1.046262e+05
3.970000
3.484505e+05
10847.000000
1999.750000
50%
2.424650e+04
2.029340e+05
4.120000
6.543600e+05
19901.000000
2003.000000
75%
2.756655e+05
4.999625e+05
4.270000
1.299898e+06
36667.500000
2006.000000
max
5.289286e+07
2.959668e+06
4.620000
6.808998e+06
169961.000000
2019.000000
Abaterea standarda
Ce este std sau abaterea standardă (standard deviation)?
Deja sunteți familiare cu histograma, știți ce înseamnă distribuția valorilor într-o histogramă. Un aspect interesant al distribuției este variabilitatea (variability) valorilor.
a = [1, 1, 1, 1]
b = [1, 3, 3, 1]
c = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19]
# In care din listele de mai sus, valorile variaza? In care variaza cel mai mult?
# Cat de mult variaza?
Ca sa ne dăm seama cât de mult variază valorile într-o distribuție trebuie să investigăm distanța valorilor de la media distribuției.
Ulterior însumând aceste distanțe, și împărțind totalul la numărul de valori din distribuție vom obține o medie aritmetică a distanțelor care ne va indica cât de mult variază valorile într-o distribuție.
c = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19]
c_mean = sum(c)/len(c)
distances = []
for num in c:
distance = num - c_mean
distances.append(distance)
distances
[-1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, 16.5]
sum(distances)
0.0
De ce am obținut suma = 0?
Din câte observăm suma totală a volorilor sub medie este egală cu suma totală a valorilor deasupra mediei.
Ce trebuie să facem ca să nu obținem suma = 0?
# transformăm distanțele în valori absolute, astfel ne asigurăm că toate vor fi valori pozitive
distances = []
for num in c:
distance = abs(num - c_mean)
distances.append(distance)
distances
[1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 16.5]
sum(distances)
33.0
# Împărțim suma distanțelor absolute la numărul de valori din distribuție
sum(distances)/len(c)
2.75
Valoarea de mai sus, 2.75, reprezintă distanța medie absolută (mean absolute distance), sau în statistică se mai numește abaterea medie absolută (mean absolute deviation).
O altă soluție de a evita suma = 0, e să ridicăm la puterea a doua toate distanțele.
distances = []
for num in c:
distance = (num - c_mean)**2
distances.append(distance)
distances
[2.25, 2.25, 2.25, 2.25, 2.25, 2.25, 2.25, 2.25, 2.25, 2.25, 2.25, 272.25]
Care este avantajul de a folosi valori pătratice față de valori absolute?
# Împărțim suma distanțelor pătratice la numărul de valori din distribuție
sum(distances)/len(c)
24.75
Valoarea 24.75 reprezintă distanța medie patratică (mean squared distance) sau variația (variance) valorilor într-o distribuție.
Acum această valoare trebuie să fie standardizată sau adusă la "starea normală" și vom face asta prin extragerea rădăcinii pătrate.
import math
math.sqrt(sum(distances)/len(c))
4.9749371855331
Valoarea ~4.97 am obținut-o extragând rădăcina pătrată din distanța medie pătratică, această valoare reprezintă abaterea standardă (standard deviation).
La ce ne ajută abaterea standardă?
Imaginați-vă că vreți să cumpărați o casă. Și prețul acestei case este de 60000 de euro. Vă întrebați dacă această casă este scumpă, sau nu, față de restul caselor de pe stradă. Să presupunem că avem această listă de prețuri ale caselor de pe această stradă.
preturi = [10700, 120000, 20000, 35000, 78000, 45500, 90000, 100000, 19000, 60000, 40000, 51000, 55000, 72000,
20500, 35500, 79500, 45500, 90500, 105000, 19500, 65000, 43000, 51500, 135000, 55500, 72500, 115000, 29000, 150000]
mean = sum(preturi)/len(preturi)
print(mean)
import statistics
standard_dev = statistics.stdev(preturi)
print(standard_dev)
plt.hist(preturi)
plt.axvline(mean, color = 'r', label = 'medie')
plt.axvline(mean - standard_dev, color = 'g', label = 'std_sub_medie')
plt.axvline(mean + standard_dev, color = 'y', label = 'std_deasupra mediei')
plt.legend()
63623.333333333336
36599.94990889104
<matplotlib.legend.Legend at 0x7f0f8fe4dba8>

Unde se plasează 60000 de euro? Între axa verde și roșie, sau între axa roșie și galbenă? Observăm că 60000 de euro este un preț ușor mai mic decât media prețurilor caselor de pe stradă dar totuși nu e un preț foarte mic pentru că nu trece peste limita unei abateri standarde sub medie.
Surse adiționale:
Percentile
Ce sunt percentilele?
Percentila este o mărime care se folosește în statistică și indică câte procente din populația distribuită crescător după o anumită valoare se află până la aceasta.
De exemplu până la a 10 percentilă se află 10 procente din populație. După a 10-a percentilă se află 90% din populație.
A 25-a, 50-a, 75-a percentilă se mai numesc cuartile (quartiles): Q1, Q2, Q3.
# Admitem că avem o populație de 10 persoane care au înălțimile de mai jos:
inaltimi = [150, 149, 168, 170, 190, 201, 182, 175, 163, 158]
inaltimi_sortate = sorted(inaltimi)
inaltimi_sortate
[149, 150, 158, 163, 168, 170, 175, 182, 190, 201]
# La a câta percentilă se află persoana cu înălțimea 158? Ce înseamnă asta?
# Până la ce înălțime ajunge 50% din populație?
# Revenind la cărți:
# Q1(25%) are valoarea rating-ului de 3.97. Ce inseamnă asta?
# Ce puteți să spuneți despre 75% din cărți si anul lor de editare?
Resurse utile: Video varianta, standard deviation
Metode: Series
books['Rating'].max()
4.62
books['Rating'].min()
3.41
# Aflați minimul și maximul coloanei care indică numărul de pagini
# .....
books['Rating'].sum()
785.23
# Aflați câte persoane în total au scris review-uri pentru cârți?
# ....
books['Rating'].mean()
4.111151832460733
books['Rating'].median()
4.12
books['Rating'].mode()
0 4.23
dtype: float64
Metoda value_counts() returnează frecvența valorilor dintr-o coloană.
books['Rating'].value_counts()
# ce observați referitor la funcția mode() și valorile de mai jos?
# Parametri:
# normalize=True * 100
# sort = False
# ascending = True
# bins
# dropna = False
4.23 7
4.12 5
4.36 5
3.98 5
4.26 5
..
3.69 1
3.95 1
4.54 1
3.83 1
3.77 1
Name: Rating, Length: 80, dtype: int64
Documentație: Series.value_counts()
# Aflați câte cărți avem reprezentative pentru fiecare gen?
# Depistați dacă sunt date lipsă și arătați valorile în procente
# ...
books['Rating'].sort_values(ascending=False)
34 4.62
119 4.60
92 4.58
65 4.57
77 4.57
...
151 NaN
155 NaN
160 NaN
185 NaN
186 NaN
Name: Rating, Length: 200, dtype: float64
books['Authour'].unique()
array(['Stephen Chbosky', 'Khaled Hosseini', 'Nicholas Sparks',
'Margaret Wise Brown', 'Herman Melville', 'Cassandra Clare',
'Mary Wollstonecraft Shelley', 'Dr. Seuss',
'Gabriel García Márquez', 'Edgar Allan Poe', 'Louis Sachar',
'Louisa May Alcott', 'Erich Maria Remarque', 'Richelle Mead',
'Suzanne Collins', 'Rick Riordan', 'Arthur Conan Doyle',
'William Goldman', "Madeleine L'Engle", 'Lewis Carroll',
'Yann Martel', 'Jeffrey Eugenides', 'C.S. Lewis', 'Kahlil Gibran',
'Alice Sebold', 'Jane Carruth', 'Fyodor Dostoyevsky',
'Frank McCourt', 'Stephenie Meyer', 'William Golding',
'Arthur Golden', 'Ken Follett', 'J.K. Rowling', 'Diana Gabaldon',
'Eric Carle', 'Stieg Larsson', 'Umberto Eco', 'George R.R. Martin',
'Patrick Rothfuss', 'Marion Zimmer Bradley', 'Jodi Picoult',
'Alexandre Dumas', 'Franz Kafka', 'Wilson Rawls', 'Jack London',
'J.D. Salinger', 'Kurt Vonnegut Jr.', 'Amy Tan', 'Ian McEwan',
'Margaret Mitchell', 'Charles Dickens', 'Philip Pullman',
'J.M. Barrie', 'Frank Herbert', 'George Orwell', 'Paulo Coelho',
'Kathryn Stockett', 'John Steinbeck', 'S.E. Hinton', 'John Green',
'Miguel de Cervantes Saavedra', 'John Irving', 'Betty Smith',
'Jay Asher', 'Charlotte Brontë', 'William Shakespeare',
'Alan Moore', 'Stephen King', 'Christopher Paolini', 'Victor Hugo',
'Elizabeth Gilbert', 'Hermann Hesse', 'Barbara Kingsolver',
'Milan Kundera', 'Cormac McCarthy', 'Richard Bach', 'Homer',
'Ernest Hemingway', 'Alice Walker', 'Antoine de Saint-Exupéry',
'Margaret Atwood', 'Maurice Sendak', 'Dante Alighieri',
'Agatha Christie', 'Katherine Paterson', 'A.A. Milne',
'Norton Juster', 'Emily Brontë', 'Shel Silverstein', 'Roald Dahl',
'Terry Pratchett', 'Jack Kerouac', 'Truman Capote',
'Pearl S. Buck', 'Oscar Wilde', 'J.R.R. Tolkien', 'Joseph Conrad',
'Anita Diamant', 'Colleen McCullough', 'Markus Zusak',
'Zora Neale Hurston', 'Laura Ingalls Wilder', 'Neil Gaiman',
'Richard Adams', 'Geoffrey Chaucer', 'Nathaniel Hawthorne',
'Larry McMurtry', 'Aldous Huxley', 'Frances Hodgson Burnett',
'Joseph Heller', 'Mario Puzo', 'Veronica Roth', 'Gustave Flaubert',
'Audrey Niffenegger', 'Douglas Adams', 'L.M. Montgomery',
'Vladimir Nabokov', 'Anne Rice', 'Orson Scott Card', 'E.L. James',
'Leo Tolstoy', 'Carlos Ruiz Zafón', 'Mitch Albom', 'Sara Gruen',
'Mikhail Bulgakov', 'Ray Bradbury', 'Mark Twain',
'F. Scott Fitzgerald', 'Michael Ende', 'E.B. White',
'Patrick Süskind', 'Becca Fitzpatrick', 'Mark Haddon',
'James Dashner', 'L. Frank Baum', 'Anthony Burgess', 'Ken Kesey',
'Sylvia Plath', 'Daniel Keyes', 'Lois Lowry', 'James Joyce',
'Dan Brown', 'Chuck Palahniuk', 'Jean M. Auel', 'Albert Camus',
'Harper Lee', 'Reduced Shakespeare Company',
'Robert Louis Stevenson', 'Jane Austen', 'Sue Monk Kidd',
'Daphne du Maurier', 'Thomas Hardy', 'Bram Stoker', 'Ayn Rand'],
dtype=object)
books['Authour'].nunique()
154
Metode înlănțuite
Conceptul de metode înlănțuite permite aplicarea mai multor metode una peste rezultatul alteia într-o linie de cod.
books['Rating'].value_counts()
# .sum()
4.23 7
4.12 5
4.36 5
3.98 5
4.26 5
..
3.69 1
3.95 1
4.54 1
3.83 1
3.77 1
Name: Rating, Length: 80, dtype: int64
books['Rating'].value_counts().head()
4.23 7
4.12 5
4.36 5
3.98 5
4.26 5
Name: Rating, dtype: int64
books['Rating'].value_counts().head().hist()

Pandas are încorporate metode de plotare bazate pe metodele din matplotlib.
Selectarea cu loc[] și iloc[]
loc[]
Loc este o proprietate prezentă și la clasa DataFrame, și la clasa Series. Această proprietate permite selectarea elementelor din DataFrame sau Series prin indexare.
books.head()
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
#sintaxa pentru selectarea unui item din DataFrame:
# books.loc[row_label,column_label]
books.loc[0,'Id']
22628
# Selectăm o coloană
# books.loc[:,'Id']
# prescurtare convențională:
books['Id']
0 22628
1 77203
2 35545737
3 32929
4 153747
...
195 17899948
196 32261
197 7126
198 17245
199 662
Name: Id, Length: 200, dtype: int64
# selectăm o listă de coloane
# books.loc[:,['Name', 'Score']]
# prescurtare convențională:
books[['Name', 'Score']]
Name
Score
0
The Perks of Being a Wallflower
745557
1
The Kite Runner
427631
2
A Walk to Remember
104093
3
Goodnight Moon
93488
4
Moby-Dick or, the Whale
200963
...
...
...
195
Rebecca
328317
196
Tess of the D'Urbervilles
88562
197
The Count of Monte Cristo
116688
198
Dracula
636610
199
Atlas Shrugged
247445
200 rows × 2 columns
# selectăm un slice de coloane
books.loc[:,'Id':'Authour']
Id
Name
Authour
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
1
77203
The Kite Runner
Khaled Hosseini
2
35545737
A Walk to Remember
Nicholas Sparks
3
32929
Goodnight Moon
Margaret Wise Brown
4
153747
Moby-Dick or, the Whale
Herman Melville
...
...
...
...
195
17899948
Rebecca
Daphne du Maurier
196
32261
Tess of the D'Urbervilles
Thomas Hardy
197
7126
The Count of Monte Cristo
Alexandre Dumas
198
17245
Dracula
Bram Stoker
199
662
Atlas Shrugged
Ayn Rand
200 rows × 3 columns
# selectează un rând
books.loc[0]
Id 22628
Name The Perks of Being a Wallflower
Authour Stephen Chbosky
Score 745557
Rating 4.2
Rating Count 1219410
Review Count 56409
Page Count 213p
Year 1999
Genres NaN
Name: 0, dtype: object
# selectează mai multe rânduri
books.loc[[2, 4, 6]]
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
6
35031085
Frankenstein: The 1818 Text
Mary Wollstonecraft Shelley
430783
3.80
1132408
31805
288p
2018
Classics
# selectează un slice de rânduri dintr-un DataFrame
books.loc[0:2, 'Id':'Score']
# prescurtare convențională:
# books[0:2]
Id
Name
Authour
Score
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
1
77203
The Kite Runner
Khaled Hosseini
427631
2
35545737
A Walk to Remember
Nicholas Sparks
104093
# exercițiu: vrem să selectăm de la rândul 2 până la 4 și de la coloana 'name' la coloana 'score'
books.loc[2:4, 'Name':'Score']
Name
Authour
Score
2
A Walk to Remember
Nicholas Sparks
104093
3
Goodnight Moon
Margaret Wise Brown
93488
4
Moby-Dick or, the Whale
Herman Melville
200963
# selectează un item din Series
# books['Name'].loc[4]
# prescurtare convențională:
books['Name'][4]
'Moby-Dick or, the Whale'
# selectează o listă de itemi din Series
# books['Name'].loc[[2, 5, 8]]
# prescurtare convențională:
books['Name'][[2, 5, 8]]
2 A Walk to Remember
5 City of Bones (The Mortal Instruments, #1)
8 One Hundred Years of Solitude
Name: Name, dtype: object
# selectează un slice de itemi din Series
# books['Name'].loc[3:4]
# prescurtare convențională:
books['Name'][3:5]
3 Goodnight Moon
4 Moby-Dick or, the Whale
Name: Name, dtype: object
# selectează din coloana 'Score' itemii 3, 7, 2
books['Score'].loc[[3, 7, 2]]
# selectează din coloana 'Genres' de la al 9-lea pâna la al 15-lea item.
3 93488
7 78563
2 104093
Name: Score, dtype: int64
books['Genres'][9:16]
9 Classics
10 Young Adult
11 Classics
12 Historical
13 Young Adult
14 Young Adult
15 Fantasy
Name: Genres, dtype: object
iloc[]
Iloc este la fel o proprietate a claselor DataFrame și Series. Cu iloc putem să selectăm coloanele sau rândurile doar după indecșii numerici.
books.head()
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
# sintaxa pentru iloc[]: df.iloc[row_index, column_index]
books.iloc[0, 0]
22628
books.iloc[[2, 4, 6]]
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
6
35031085
Frankenstein: The 1818 Text
Mary Wollstonecraft Shelley
430783
3.80
1132408
31805
288p
2018
Classics
# Selectează din tabelul books de la rândul 2 la rândul 9 și de la coloana 1 la coloana 4
books.iloc[2:10, 1:5]
Name
Authour
Score
Rating
2
A Walk to Remember
Nicholas Sparks
104093
4.18
3
Goodnight Moon
Margaret Wise Brown
93488
4.28
4
Moby-Dick or, the Whale
Herman Melville
200963
3.50
5
City of Bones (The Mortal Instruments, #1)
Cassandra Clare
713154
4.10
6
Frankenstein: The 1818 Text
Mary Wollstonecraft Shelley
430783
3.80
7
Oh, the Places You'll Go!
Dr. Seuss
78563
4.36
8
One Hundred Years of Solitude
Gabriel García Márquez
613129
4.08
9
The Complete Stories and Poems
Edgar Allan Poe
213957
4.38
Selectearea prin indexarea cu boolean
O metodă pentru a selecta condiționat este folosirea indexării cu valori boolean.
books['Year'] == 2006
0 False
1 False
2 False
3 False
4 False
...
195 False
196 False
197 False
198 False
199 False
Name: Year, Length: 200, dtype: bool
bool_2006 = books['Year'] == 2006
bool_2006
0 False
1 False
2 False
3 False
4 False
...
195 False
196 False
197 False
198 False
199 False
Name: Year, Length: 200, dtype: bool
Cu ajutorul Seriei vom indexa în DataFrame doar rândurile cu valoarea True.
books[bool_2006]
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
20
4214
Life of Pi
Yann Martel
485940
3.91
1309184
46807
460p
2006
Fiction
24
12232938
The Lovely Bones
Alice Sebold
508104
3.81
1977504
40105
372p
2006
Fiction
28
41865
Twilight (Twilight, #1)
Stephenie Meyer
1452846
3.59
4839503
102492
501p
2006
Young Adult
51
7763
The Joy Luck Club
Amy Tan
81845
3.93
590245
9020
288p
2006
Fiction
64
28187
The Lightning Thief (Percy Jackson and the Oly...
Rick Riordan
573399
4.25
1922316
58816
375p
2006
Fantasy
69
14891
A Tree Grows in Brooklyn
Betty Smith
307886
4.27
380787
20170
496p
2006
Classics
77
1
Harry Potter and the Half-Blood Prince (Harry ...
J.K. Rowling
155771
4.57
2363861
38035
652p
2006
Fantasy
86
99561
Looking for Alaska
John Green
138376
NaN
1084064
55417
221p
2006
Young Adult
87
6288
The Road
Cormac McCarthy
298802
3.97
700221
45005
241p
2006
Fiction
88
71728
Jonathan Livingston Seagull
Richard Bach
80428
3.84
196608
7693
112p
2006
NaN
90
1381
The Odyssey
Homer
488592
3.77
844968
11868
541p
2006
Classics
113
12067
Good Omens: The Nice and Accurate Prophecies o...
Terry Pratchett
90852
4.25
520130
26583
491p
2006
Fantasy
123
19063
The Book Thief
Markus Zusak
1343484
4.37
1779061
111157
552p
2006
NaN
125
37415
Their Eyes Were Watching God
Zora Neale Hurston
95935
3.92
253858
12964
219p
2006
Classics
153
28186
The Sea of Monsters (Percy Jackson and the Oly...
Rick Riordan
82179
4.24
717600
25902
279p
2006
Fantasy
161
24583
The Adventures of Tom Sawyer
Mark Twain
146031
3.91
739818
9690
244p
2006
Classics
175
6514
The Bell Jar
Sylvia Plath
345502
4.01
573995
22336
294p
2006
Classics
177
3636
The Giver (The Giver, #1)
Lois Lowry
407467
4.13
1729590
64308
208p
2006
Young Adult
182
968
The Da Vinci Code (Robert Langdon, #2)
Dan Brown
867513
3.85
1887312
46482
489p
2006
Fiction
190
2657
To Kill a Mockingbird
Harper Lee
2235010
4.28
4377280
89241
324p
2006
Classics
Indexarea boolean de fapt e selectarea unui slice de rânduri.
# să ne amintim cum selectăm un slice într-un DataFrame
books.loc[2:3, 'Name']
2 A Walk to Remember
3 Goodnight Moon
Name: Name, dtype: object
# același principiu îl folosim când vrem să selectăm doar numele cărților din anul 2006
books.loc[bool_2006, 'Name']
20 Life of Pi
24 The Lovely Bones
28 Twilight (Twilight, #1)
51 The Joy Luck Club
64 The Lightning Thief (Percy Jackson and the Oly...
69 A Tree Grows in Brooklyn
77 Harry Potter and the Half-Blood Prince (Harry ...
86 Looking for Alaska
87 The Road
88 Jonathan Livingston Seagull
90 The Odyssey
113 Good Omens: The Nice and Accurate Prophecies o...
123 The Book Thief
125 Their Eyes Were Watching God
153 The Sea of Monsters (Percy Jackson and the Oly...
161 The Adventures of Tom Sawyer
175 The Bell Jar
177 The Giver (The Giver, #1)
182 The Da Vinci Code (Robert Langdon, #2)
190 To Kill a Mockingbird
Name: Name, dtype: object
# exercițiu:
# 1. selectați toate cărțile din genul "Historical" și afișați doar numele acestora
# 2. selectați toate cărțile din genul 'Romance' și afișati numele și scorul acestora
# 3. selectați toate cărțile din genul 'Horror' care să conțină coloanele de la 'rating' până la 'page_count'
Variabila bool_2006 e doar o variabilă. Putem să scriem expresia boolean direct în sintaxa de selectare.
bool_2006 = books['Year'] == 2006
expresia boolean: books['Year'] == 2006
books.loc[books['Year']==2006, 'Name']
20 Life of Pi
24 The Lovely Bones
28 Twilight (Twilight, #1)
51 The Joy Luck Club
64 The Lightning Thief (Percy Jackson and the Oly...
69 A Tree Grows in Brooklyn
77 Harry Potter and the Half-Blood Prince (Harry ...
86 Looking for Alaska
87 The Road
88 Jonathan Livingston Seagull
90 The Odyssey
113 Good Omens: The Nice and Accurate Prophecies o...
123 The Book Thief
125 Their Eyes Were Watching God
153 The Sea of Monsters (Percy Jackson and the Oly...
161 The Adventures of Tom Sawyer
175 The Bell Jar
177 The Giver (The Giver, #1)
182 The Da Vinci Code (Robert Langdon, #2)
190 To Kill a Mockingbird
Name: Name, dtype: object
Ce alte expresii boolean mai cunoaștem? Putem să le folosim ca și condiții de selectare?
# Enumerați exemple de expresii boolean și executați 3 selecții din tabel
Selectarea cu operatorii boolean
Putem să indexăm și cu o expresii logice. Vom selecta toate cărțile din 2006 care au ratingul mai mare decât 4.
books[(books['Year'] == 2006) & (books['Rating'] >= 4)]
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
64
28187
The Lightning Thief (Percy Jackson and the Oly...
Rick Riordan
573399
4.25
1922316
58816
375p
2006
Fantasy
69
14891
A Tree Grows in Brooklyn
Betty Smith
307886
4.27
380787
20170
496p
2006
Classics
77
1
Harry Potter and the Half-Blood Prince (Harry ...
J.K. Rowling
155771
4.57
2363861
38035
652p
2006
Fantasy
113
12067
Good Omens: The Nice and Accurate Prophecies o...
Terry Pratchett
90852
4.25
520130
26583
491p
2006
Fantasy
123
19063
The Book Thief
Markus Zusak
1343484
4.37
1779061
111157
552p
2006
NaN
153
28186
The Sea of Monsters (Percy Jackson and the Oly...
Rick Riordan
82179
4.24
717600
25902
279p
2006
Fantasy
175
6514
The Bell Jar
Sylvia Plath
345502
4.01
573995
22336
294p
2006
Classics
177
3636
The Giver (The Giver, #1)
Lois Lowry
407467
4.13
1729590
64308
208p
2006
Young Adult
190
2657
To Kill a Mockingbird
Harper Lee
2235010
4.28
4377280
89241
324p
2006
Classics
Vom selecta cărțile care sunt din anul 2006 sau care au ratingul mai mare decât 4.
books[(books['Year'] == 2006) | (books['Rating'] >= 4)]
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
5
256683
City of Bones (The Mortal Instruments, #1)
Cassandra Clare
713154
4.10
1577035
60639
485p
2007
Fantasy
...
...
...
...
...
...
...
...
...
...
...
193
1885
Pride and Prejudice
Jane Austen
1942736
4.26
2905431
64486
279p
2000
Classics
194
37435
The Secret Life of Bees
Sue Monk Kidd
178535
4.05
1098795
30073
302p
2003
Fiction
195
17899948
Rebecca
Daphne du Maurier
328317
4.23
430751
22157
449p
2013
Classics
197
7126
The Count of Monte Cristo
Alexandre Dumas
116688
4.25
731027
20622
1276p
2003
Classics
198
17245
Dracula
Bram Stoker
636610
4.00
907768
24683
488p
1986
Classics
144 rows × 10 columns
Vom selecta toate cărțile care nu au fost editate în anul 2006.
books[~(books['Year'] == 2006)]
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
...
...
...
...
...
...
...
...
...
...
...
195
17899948
Rebecca
Daphne du Maurier
328317
4.23
430751
22157
449p
2013
Classics
196
32261
Tess of the D'Urbervilles
Thomas Hardy
88562
3.80
233821
8491
518p
2003
Classics
197
7126
The Count of Monte Cristo
Alexandre Dumas
116688
4.25
731027
20622
1276p
2003
Classics
198
17245
Dracula
Bram Stoker
636610
4.00
907768
24683
488p
1986
Classics
199
662
Atlas Shrugged
Ayn Rand
247445
3.69
348149
17053
1168p
1999
Classics
180 rows × 10 columns
# selectează toate cărțile din genul Fiction care au Ratingul mai mic sau egal 3
Înlocuirea datelor din coloană
Mai jos avem toată lista de genuri de cărți pe care le avem în setul de date books.
books['Genres'].value_counts()
Classics 72
Fiction 34
Fantasy 30
Young Adult 17
Childrens 11
Horror 4
Science Fiction 4
Romance 3
Historical 3
Nonfiction 3
Cultural 1
Plays 1
Mystery 1
Poetry 1
Sequential Art 1
Name: Genres, dtype: int64
Vrem să schimbăm valoarea 'Science Fiction' în 'SciFi'.
books.loc[books['Genres']=='Science Fiction', 'Genres'] = 'SciFi'
books['Genres'].value_counts()
Classics 72
Fiction 34
Fantasy 30
Young Adult 17
Childrens 11
SciFi 4
Horror 4
Romance 3
Historical 3
Nonfiction 3
Cultural 1
Plays 1
Mystery 1
Poetry 1
Sequential Art 1
Name: Genres, dtype: int64
Crearea coloanelor noi
Avem DataFrame-ul df.
df = pd.DataFrame([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]], columns = ['a', 'b', 'c', 'd'])
df
a
b
c
d
0
1
2
3
4
1
5
6
7
8
2
9
10
11
12
Creăm o coloană în DataFrame-ul df care să conțină valori doar de 1.
df['e'] = 1
df
a
b
c
d
e
0
1
2
3
4
1
1
5
6
7
8
1
2
9
10
11
12
1
# creați o coloană în DataFrame-ul df care va conține numere de la 1 la 3. Folosiți range().
# ....
Operațiuni vectorizate
df['de'] = df['d']+df['e']
df
a
b
c
d
e
de
0
1
2
3
4
1
5
1
5
6
7
8
1
9
2
9
10
11
12
1
13
Operații:
series_a + series_b
- Adunareseries_a - series_b
- Scădereseries_a * series_b
- înmulțireseries_a / series_b
- Împărțire
Putem să folosim și alte operațiuni matematice.
df['f'] = df['d']**df['de']
df
a
b
c
d
e
de
f
0
1
2
3
4
1
5
1024
1
5
6
7
8
1
9
134217728
2
9
10
11
12
1
13
106993205379072
Concatenare.
df = pd.DataFrame([['a', 'b'],
['c', 'd'],
['e', 'f']], columns = ['A', 'B'])
df
A
B
0
a
b
1
c
d
2
e
f
df['C'] = df['A'] + df['B']
df
A
B
C
0
a
b
ab
1
c
d
cd
2
e
f
ef
# exercițiu: Aflati diferența dintre numărul de persoane care dau review și numărul de peroane care pun note. Creați o coloană nouă pentru rezultat.
# ....
Curățirea datelor
Modificarea denumirilor de coloane
books.columns
Index(['Id', 'Name', 'Authour', 'Score', 'Rating', 'Rating Count',
'Review Count', 'Page Count', 'Year', 'Genres'],
dtype='object')
Convențional numele coloanelor din Pandas trebuie sa fie în formatul snake_case
.
Pentru a modifica numele coloanelor folosim metoda rename()
în care specificăm la parametrul columns
un dicționar în care cheile sunt numele coloanelor existente, iar valorile sunt numele coloanelor propuse.
# Mai întâi creăm o copie a DataFrame-ului books.
books_copy = books.copy()
books_copy.rename(columns={
'Id':'id',
'Name':'name',
'Authour':'authour',
'Score':'score',
'Rating':'rating',
'Rating Count': 'rating_count',
'Review Count': 'review_count',
'Page Count': 'page_count',
'Year':'year',
'Genres':'genres'
})
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
...
...
...
...
...
...
...
...
...
...
...
195
17899948
Rebecca
Daphne du Maurier
328317
4.23
430751
22157
449p
2013
Classics
196
32261
Tess of the D'Urbervilles
Thomas Hardy
88562
3.80
233821
8491
518p
2003
Classics
197
7126
The Count of Monte Cristo
Alexandre Dumas
116688
4.25
731027
20622
1276p
2003
Classics
198
17245
Dracula
Bram Stoker
636610
4.00
907768
24683
488p
1986
Classics
199
662
Atlas Shrugged
Ayn Rand
247445
3.69
348149
17053
1168p
1999
Classics
200 rows × 10 columns
books_copy
# ce observăm?
# modificările nu s-au salvat
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
...
...
...
...
...
...
...
...
...
...
...
195
17899948
Rebecca
Daphne du Maurier
328317
4.23
430751
22157
449p
2013
Classics
196
32261
Tess of the D'Urbervilles
Thomas Hardy
88562
3.80
233821
8491
518p
2003
Classics
197
7126
The Count of Monte Cristo
Alexandre Dumas
116688
4.25
731027
20622
1276p
2003
Classics
198
17245
Dracula
Bram Stoker
636610
4.00
907768
24683
488p
1986
Classics
199
662
Atlas Shrugged
Ayn Rand
247445
3.69
348149
17053
1168p
1999
Classics
200 rows × 10 columns
# ce trebuie sa facem ca să salvăm modificările?
# .....
# salvăm modificările:
# soluția 1
books_copy_renamed_col = ...
# salvăm modificările:
# soluția 2
books_copy.rename(columns={
'Id':'id',
'Name':'name',
'Authour':'authour',
'Score':'score',
'Rating':'rating',
'Rating Count': 'rating_count',
'Review Count': 'review_count',
'Page Count': 'page_count',
'Year':'year',
'Genres':'genres'
}, inplace = True)
Dar atunci când avem un tabel cu vreo 80 de coloane cărora trebuie să le modificăm numele. Ar trebui să creăm un dicționar manual prea mare.
books.head()
Id
Name
Authour
Score
Rating
Rating Count
Review Count
Page Count
Year
Genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
Sau o alternativă ar putea fi să utilizăm metodele Clasei String
. De exemplu metoda lower()
, transformă toate literele din string în litere mici.
'Name'.lower()
'name'
Iar cu ajutorul metodei replace() putem să identificăm un caracter din string pe care vrem să-l înlocuim, îl menționăm ca prim parametru, iar al doilea parametru va fi caracterul cu care vrem să-l înlocuim. În cazul dat vom înlocui spațiul gol dintre 2 caractere cu ”_”
.
'Rating Count'.replace(' ', '_')
# folosește conceptul de metode înlănțuite
# .lower()
'Rating_Count'
Acum să scriem o funcție care utilizează cele 2 metode string de mai sus.
def clean_col(col):
col = col.replace(' ', '_').lower()
return col
Ca să schimbăm numele coloanelor vom folosi un loop for ca să iterăm prin books.columns
și vom apela funcția *clean_col*
pentru fiecare string books.columns
.
# amintiți-vă ce returnează books.columns
# .....
new_columns = []
for col in books.columns:
column = clean_col(col)
new_columns.append(column)
new_columns
['id',
'name',
'authour',
'score',
'rating',
'rating_count',
'review_count',
'page_count',
'year',
'genres']
Iar acum atribuim lui books.columns lista creată cu numele noi de coloane.
books.columns = new_columns
books.head()
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
Datele lipsă
Metoda isnull()
ne returnează tabelul books
cu valori boolean.
books.isnull()
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
0
False
False
False
False
False
False
False
False
False
True
1
False
False
False
False
False
False
False
False
False
False
2
False
False
False
False
False
False
False
False
False
False
3
False
False
False
False
False
False
False
False
False
False
4
False
False
False
False
False
False
False
False
False
False
...
...
...
...
...
...
...
...
...
...
...
195
False
False
False
False
False
False
False
False
False
False
196
False
False
False
False
False
False
False
False
False
False
197
False
False
False
False
False
False
False
False
False
False
198
False
False
False
False
False
False
False
False
False
False
199
False
False
False
False
False
False
False
False
False
False
200 rows × 10 columns
# folosim conceptul de metode inlanțuite. Ce observați?
books.isnull().sum()
id 0
name 0
authour 0
score 0
rating 9
rating_count 0
review_count 0
page_count 0
year 0
genres 14
dtype: int64
Date numerice
Ștergerea datelor
Cea mai ușoară abordare e să ștergem datele lipsă. Putem să ștergem datele lipsă utilizând metoda dropna().
books_notnull = books.dropna()
books_notnull.info()
# observați ce s-a întâmplat cu datele? Câte date au fost șterse? Ce au fost șterse, rânduri, sau coloane?
<class 'pandas.core.frame.DataFrame'>
Int64Index: 177 entries, 1 to 199
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 177 non-null int64
1 name 177 non-null object
2 authour 177 non-null object
3 score 177 non-null int64
4 rating 177 non-null float64
5 rating_count 177 non-null int64
6 review_count 177 non-null int64
7 page_count 177 non-null object
8 year 177 non-null int64
9 genres 177 non-null object
dtypes: float64(1), int64(5), object(4)
memory usage: 15.2+ KB
Folosim librăria Seaborn ca să plotăm un grafic de tip heatmap, în care vedem cu culori deschise datele lipsă în dependență de coloane. Astfel putem să observăm anumite pattern-uri, de exemplu dacă datele lipsă din diferite coloane coincid după rânduri.
import seaborn as sns
sns.heatmap(books.isnull(), cbar=False)
/usr/local/lib/python3.6/dist-packages/statsmodels/tools/_testing.py:19: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.
import pandas.util.testing as tm
<matplotlib.axes._subplots.AxesSubplot at 0x7f0f81c11be0>

Atunci când vrem să ștergem coloanele cu date lipsă, trebuie să specificăm în metoda dropna()
parametrul axis
cu valoarea ”columns”
.
books.dropna(axis='columns')
id
name
authour
score
rating_count
review_count
page_count
year
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
1219410
56409
213p
1999
1
77203
The Kite Runner
Khaled Hosseini
427631
2365531
72036
371p
2004
2
35545737
A Walk to Remember
Nicholas Sparks
104093
658664
12918
215p
2000
3
32929
Goodnight Moon
Margaret Wise Brown
93488
296501
5729
32p
2007
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
470744
15149
654p
2003
...
...
...
...
...
...
...
...
...
195
17899948
Rebecca
Daphne du Maurier
328317
430751
22157
449p
2013
196
32261
Tess of the D'Urbervilles
Thomas Hardy
88562
233821
8491
518p
2003
197
7126
The Count of Monte Cristo
Alexandre Dumas
116688
731027
20622
1276p
2003
198
17245
Dracula
Bram Stoker
636610
907768
24683
488p
1986
199
662
Atlas Shrugged
Ayn Rand
247445
348149
17053
1168p
1999
200 rows × 8 columns
Dacă vrem să ștergem rândurile cu datele lipsă care aparțin doar unei coloane anumite, menționăm în metoda dropna()
parametrul subset
care ia o listă de valori cu numele coloanelor care ne interesează.
books.dropna(subset=['rating'])
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
NaN
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
...
...
...
...
...
...
...
...
...
...
...
195
17899948
Rebecca
Daphne du Maurier
328317
4.23
430751
22157
449p
2013
Classics
196
32261
Tess of the D'Urbervilles
Thomas Hardy
88562
3.80
233821
8491
518p
2003
Classics
197
7126
The Count of Monte Cristo
Alexandre Dumas
116688
4.25
731027
20622
1276p
2003
Classics
198
17245
Dracula
Bram Stoker
636610
4.00
907768
24683
488p
1986
Classics
199
662
Atlas Shrugged
Ayn Rand
247445
3.69
348149
17053
1168p
1999
Classics
191 rows × 10 columns
# Cum credeți care ar fi o abordare mai corectă? Să ștergem rânduri sau coloane?
# În ce cazuri ați folosi o abordare sau alta?
O altă abordare este înlocuirea datelor lipsă cu valori.
Estimarea valorilor lipsă
Puteți să investigați setul de date și să estimați valorile lipsă bazându-vă pe dependențele față de valorile din alte coloane.
Dependența rating-ului față de celelalte valori este foarte mică, respectiv nu putem estima valorile lipsă după acest criteriu.
Înlocuirea cu media valorilor din coloană.
books_miss_val1 = books.copy()
rating_mean = books_miss_val1['rating'].mean()
rating_mean
4.111151832460733
Metoda fillna() înlocuiește toate valorile NaN cu valoarea care ne-o dorim noi. În cazul dat va fi media aritmetică a valorilor din coloana ”rating”
.
books_miss_val1['rating'].fillna(rating_mean, inplace=True)
Înlocuirea cu mediana valorilor din coloană.
books_miss_val2 = books.copy()
rating_median = books_miss_val2['rating'].median()
rating_median
4.12
books_miss_val2['rating'].fillna(rating_median, inplace=True)
plt.hist(books['rating']);
plt.axvline(books['rating'].mean(), color='r', label = "mean")
plt.axvline(books['rating'].median(), color='y', label = "median")
plt.legend()
/usr/local/lib/python3.6/dist-packages/numpy/lib/histograms.py:839: RuntimeWarning: invalid value encountered in greater_equal
keep = (tmp_a >= first_edge)
/usr/local/lib/python3.6/dist-packages/numpy/lib/histograms.py:840: RuntimeWarning: invalid value encountered in less_equal
keep &= (tmp_a <= last_edge)
<matplotlib.legend.Legend at 0x7f0f81318978>

Ce abordare să folosiți?
Depinde de scopul proiectului.
Dacă aveți nevoie de o acuratețe maximă în date pentru a efectua studii statistice, atunci este indicat ca datele să fie șterse.
Dacă aceste date trebuie sa le folosiți pentru a antrena un model în Machine Learning și setul de date este foarte mic, atunci puteți sa înlocuiți aceste date cu media sau mediana.
Înlocuiți cu media aritmetică atunci când distribuția este aproximativ normală, pentru că media și mediana se află la mijloc și aproape coincid, respectiv valorile lor nu se vor schimba foarte mult.
Atunci cand aveți o distribuție asimetrică, cu multe valori extreme, este indicat să folosiți mediana, pentru că în cazul dat mediana se va afla în zona unde se concentrează cele mai multe valori, iar media aritmetică este mai deplasată spre valorile extreme, astfel dacă înlocuim datele lipsa cu media aritmetică, aceasta va influența distribuția.
Dacă datele poti fi estimate pe baza dependențelor față de alți parametri din setul de date, atunci asta ar fi o soluție care ne garantează valori cât de cât apropiate de realitate.
În cazul nostru, vom opta pentru ștergerea datelor.
books.dropna(subset=['rating'], inplace = True)
books.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 191 entries, 0 to 199
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 191 non-null int64
1 name 191 non-null object
2 authour 191 non-null object
3 score 191 non-null int64
4 rating 191 non-null float64
5 rating_count 191 non-null int64
6 review_count 191 non-null int64
7 page_count 191 non-null object
8 year 191 non-null int64
9 genres 177 non-null object
dtypes: float64(1), int64(5), object(4)
memory usage: 16.4+ KB
Date categoriale
Crearea categoriei valorilor lipsă.
books['genres'].value_counts(dropna = False)
Classics 68
Fiction 34
Fantasy 27
Young Adult 16
NaN 14
Childrens 11
SciFi 4
Horror 4
Historical 3
Nonfiction 3
Romance 2
Cultural 1
Plays 1
Mystery 1
Poetry 1
Sequential Art 1
Name: genres, dtype: int64
Observăm ca avem 14 valori NaN în coloana Genres. Când avem valori lipsă de tip categoriale este indicat ca ele să fie transformate într-o categorie a datelor lipsă. În cazul dat această categorie se va numi ”Unknown”
(Necunoscute).
books['genres'].fillna('Unknown', inplace = True)
books.head()
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213p
1999
Unknown
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371p
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215p
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32p
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654p
2003
Classics
books.isnull().sum()
id 0
name 0
authour 0
score 0
rating 0
rating_count 0
review_count 0
page_count 0
year 0
genres 0
dtype: int64
Modificarea datelor
books.info()
# ce observăm la tipurile de date?
<class 'pandas.core.frame.DataFrame'>
Int64Index: 191 entries, 0 to 199
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 191 non-null int64
1 name 191 non-null object
2 authour 191 non-null object
3 score 191 non-null int64
4 rating 191 non-null float64
5 rating_count 191 non-null int64
6 review_count 191 non-null int64
7 page_count 191 non-null object
8 year 191 non-null int64
9 genres 191 non-null object
dtypes: float64(1), int64(5), object(4)
memory usage: 16.4+ KB
books['page_count'].head()
# ce date din tabel ar trebui modificate?
0 213p
1 371p
2 215p
3 32p
4 654p
Name: page_count, dtype: object
Librăria Pandas conține o mulțime de metode string vectorizate pe care noi le putem folosi ca să manipulăm datele de tip string
. Multe din ele îs similare cu metodele clasei String din Python.
Majoritatea metodelor string vectorizate sunt disponibile folosind accesorul Series.str
ceea ce înseamnă că noi le putem accesa adaugând str
între numele Seriei și numele metodei, conform sinatxei de mai jos:
Documentație: Metode string vectorizate
În cazul valorilor din coloana 'page_count'
, noi vrem să selectăm caracterul 'p'
și să-l înlocuim cu nimic, astfel încât să ne rămână în această coloană doar valori de tip integer. Acest lucru putem sa-l realizăm folosind metoda string str.replace()
.
books["page_count"].str.replace('p','')
0 213
1 371
2 215
3 32
4 654
...
195 449
196 518
197 1276
198 488
199 1168
Name: page_count, Length: 191, dtype: object
Următorul pas e să transformăm aceste valori în valori de tip integer cu ajutorul metodei astype().
books['page_count'] = books['page_count'].str.replace('p', '').astype('int')
# vom obține o eroare. de ce?
# hai sa folosim aceste 2 metode "înlănțuit"
books.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 191 entries, 0 to 199
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 191 non-null int64
1 name 191 non-null object
2 authour 191 non-null object
3 score 191 non-null int64
4 rating 191 non-null float64
5 rating_count 191 non-null int64
6 review_count 191 non-null int64
7 page_count 191 non-null int64
8 year 191 non-null int64
9 genres 191 non-null object
dtypes: float64(1), int64(6), object(3)
memory usage: 16.4+ KB
Verficarea existenței rândurilor duplicate
În dependeță de metoda de colectare a datelor variază consistența datelor în set. Deseori în set se pot găsi date care se repetă, acestea se numesc duplicate.
O metodă care ne ajută să le identificăm este duplicated()
. Această metodă are parametrul keep
care are valorile 'first'
, 'last'
sau False
.
Folosim valoarea 'first'
atunci cand vrem să selectăm toate duplicatele în afară de primul.
Folosim valoarea 'last'
atunci când vrem să selectăm toate duplicatele în afară de ultimul.
Folosim valoarea False
ca să selectăm toate duplicatele din setul de date.
# books.duplicated(keep=False)
# utilizăm indexarea boolean ca să afișăm rândurile duplicate
# cum selectăm toate rândurile care nu sunt duplicate?
books[books.duplicated(keep=False)]
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
Documentaie: drop_duplicates
books.drop_duplicates(subset='name', inplace = True)
DataFrame.groupby()
Separarea în grupuri
Aplicarea unei funcții asupra fiecărui grup
Combinarea rezultatelor într-o structură de date
Pandas are o operație built-in pentru aceste 3 procese de mai sus. Operația groupby
aplică procesul de ”separare-aplicare-combinare” asupra unui DataFrame și condensează acest proces în 2 pași: 1. Crează un obiect GroupBy 2. Aplică o funcție asupra obiectului GroupBy.
Obiectul GroupBy ne permite să separăm DataFrame-ul în grupuri, dar într-un mod abstract. Nu se produce nici o operațiune până când asupra obiectului nu se aplică o funcțe.
# Creăm obiectul GroupBy.
grouped = books.groupby('genres')
grouped
Înainte de agregare(=unire), o să folosim metoda get_group()
care aparține clasei DataFrameGroupBy. Această metodă ne permite să selectăm datele pentru un grup anumit.
grouped.get_group('Classics')
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654
2003
Classics
6
35031085
Frankenstein: The 1818 Text
Mary Wollstonecraft Shelley
430783
3.80
1132408
31805
288
2018
Classics
9
23919
The Complete Stories and Poems
Edgar Allan Poe
213957
4.38
213034
2166
821
1984
Classics
11
1934
Little Women
Louisa May Alcott
340652
4.08
1637926
29378
449
2004
Classics
19
24213
Alice's Adventures in Wonderland & Through the...
Lewis Carroll
825095
4.06
446019
10321
239
2000
Classics
...
...
...
...
...
...
...
...
...
...
...
195
17899948
Rebecca
Daphne du Maurier
328317
4.23
430751
22157
449
2013
Classics
196
32261
Tess of the D'Urbervilles
Thomas Hardy
88562
3.80
233821
8491
518
2003
Classics
197
7126
The Count of Monte Cristo
Alexandre Dumas
116688
4.25
731027
20622
1276
2003
Classics
198
17245
Dracula
Bram Stoker
636610
4.00
907768
24683
488
1986
Classics
199
662
Atlas Shrugged
Ayn Rand
247445
3.69
348149
17053
1168
1999
Classics
68 rows × 10 columns
Acum să grupăm aceste grupuri folosind metoda sum()
.
grouped.sum()
id
score
rating
rating_count
review_count
page_count
year
genres
Childrens
1043945
3097363
47.19
5538095
97202
878
21933
Classics
207659489
27940853
270.39
60793160
1445289
30084
136033
Cultural
7144
748386
4.22
604962
18302
671
2002
Fantasy
61867472
10901437
117.11
41654719
943451
14352
54131
Fiction
134737368
10567705
139.38
32195941
1096432
14056
68111
Historical
365729
681659
12.48
1491980
59886
1608
5994
Horror
1035120
855307
16.81
2934501
77510
3270
7961
Mystery
16299
157229
4.26
776718
31245
264
2004
Nonfiction
195043
355939
11.74
2713505
94842
921
6001
Plays
1423
107208
4.44
8387
131
137
1994
Poetry
2547
86141
4.23
226839
9199
127
2010
Romance
69193868
330261
8.28
1960017
32645
442
4000
SciFi
45529435
2265723
17.11
3493204
98022
2020
8032
Sequential Art
472331
114982
4.36
479760
13770
416
2005
Unknown
115383431
4698484
57.26
8797566
390736
6117
28052
Young Adult
142467241
7889683
65.97
25512111
881068
6718
32141
Folosim metoda size()
când vrem să aflăm dimensiunea fiecărui grup.
grouped.size()
genres
Childrens 11
Classics 68
Cultural 1
Fantasy 27
Fiction 34
Historical 3
Horror 4
Mystery 1
Nonfiction 3
Plays 1
Poetry 1
Romance 2
SciFi 4
Sequential Art 1
Unknown 14
Young Adult 16
dtype: int64
# transformăm în DataFrame
grouped_df = pd.DataFrame(grouped.size(), columns=['size'])
grouped_df
# observați ce fel de index avem
size
genres
Childrens
11
Classics
68
Cultural
1
Fantasy
27
Fiction
34
Historical
3
Horror
4
Mystery
1
Nonfiction
3
Plays
1
Poetry
1
Romance
2
SciFi
4
Sequential Art
1
Unknown
14
Young Adult
16
# putem să agregăm datele doar pentru o sigură coloană
grouped['review_count'].max()
genres
Childrens 17375
Classics 89241
Cultural 18302
Fantasy 108606
Fiction 84112
Historical 30707
Horror 24460
Mystery 31245
Nonfiction 53431
Plays 131
Poetry 9199
Romance 19727
SciFi 42828
Sequential Art 13770
Unknown 111157
Young Adult 169961
Name: review_count, dtype: int64
# creăm o coloană nouă
grouped_df['reviews_max'] = grouped['review_count'].max()
grouped_df.head()
size
reviews_max
genres
Childrens
11
17375
Classics
68
89241
Cultural
1
18302
Fantasy
27
108606
Fiction
34
84112
Putem să grupăm datele după mai multe coloane.
books.groupby(['genres', 'year']).mean().head(20)
id
score
rating
rating_count
review_count
page_count
genres
year
Childrens
1964
370493.0
1.012345e+06
4.380
882195.000000
17375.0
64.000000
1985
233093.0
1.188860e+05
4.170
411113.000000
5702.0
61.000000
1988
23772.0
4.941850e+05
4.300
595769.000000
9208.0
62.000000
1990
191139.0
7.856300e+04
4.360
318637.000000
5158.0
44.000000
1994
4948.0
1.360590e+05
4.300
384386.000000
7754.0
26.000000
1998
23886.0
2.120750e+05
4.335
445791.000000
9979.5
156.000000
2000
19543.0
4.998120e+05
4.220
794735.000000
11579.0
37.000000
2004
113946.0
9.734000e+04
4.370
320590.000000
3146.0
64.000000
2005
6310.0
1.425350e+05
4.140
642587.000000
11592.0
176.000000
2007
32929.0
9.348800e+04
4.280
296501.000000
5729.0
32.000000
Classics
1963
332613.0
3.467220e+05
4.190
618823.000000
10614.0
325.000000
1972
485894.0
1.381860e+05
3.820
613496.000000
16702.0
201.000000
1976
70401.0
1.399490e+05
3.620
340371.000000
14644.0
307.000000
1981
52036.0
2.697250e+05
4.030
563652.000000
16851.0
152.000000
1984
23919.0
2.139570e+05
4.380
213034.000000
2166.0
821.000000
1986
17245.0
6.366100e+05
4.000
907768.000000
24683.0
488.000000
1987
24280.0
8.039670e+05
4.170
670386.000000
17090.0
1463.000000
1989
49552.0
1.540520e+05
3.980
681177.000000
22324.0
123.000000
1990
338798.0
7.695700e+04
3.730
107514.000000
6603.0
783.000000
1995
83451.0
2.219493e+05
3.980
372193.666667
13313.0
427.666667
GroupBy.agg()
Atunci când vrem să aplicăm mai multe metode asupra grupurilor putem folosi metoda agg()
.
grouped.agg(np.sum)
# observați că atunci când o metodă este utilizată ca parametru nu mai folosim "()".
id
score
rating
rating_count
review_count
page_count
year
genres
Childrens
1043945
3097363
47.19
5538095
97202
878
21933
Classics
207659489
27940853
270.39
60793160
1445289
30084
136033
Cultural
7144
748386
4.22
604962
18302
671
2002
Fantasy
61867472
10901437
117.11
41654719
943451
14352
54131
Fiction
134737368
10567705
139.38
32195941
1096432
14056
68111
Historical
365729
681659
12.48
1491980
59886
1608
5994
Horror
1035120
855307
16.81
2934501
77510
3270
7961
Mystery
16299
157229
4.26
776718
31245
264
2004
Nonfiction
195043
355939
11.74
2713505
94842
921
6001
Plays
1423
107208
4.44
8387
131
137
1994
Poetry
2547
86141
4.23
226839
9199
127
2010
Romance
69193868
330261
8.28
1960017
32645
442
4000
SciFi
45529435
2265723
17.11
3493204
98022
2020
8032
Sequential Art
472331
114982
4.36
479760
13770
416
2005
Unknown
115383431
4698484
57.26
8797566
390736
6117
28052
Young Adult
142467241
7889683
65.97
25512111
881068
6718
32141
grouped['score'].agg([np.sum, np.mean, np.max])
sum
mean
amax
genres
Childrens
3097363
281578.454545
1012345
Classics
27940853
410894.897059
2235010
Cultural
748386
748386.000000
748386
Fantasy
10901437
403756.925926
2603171
Fiction
10567705
310814.852941
867513
Historical
681659
227219.666667
388909
Horror
855307
213826.750000
386882
Mystery
157229
157229.000000
157229
Nonfiction
355939
118646.333333
134797
Plays
107208
107208.000000
107208
Poetry
86141
86141.000000
86141
Romance
330261
165130.500000
226168
SciFi
2265723
566430.750000
1051406
Sequential Art
114982
114982.000000
114982
Unknown
4698484
335606.000000
1343484
Young Adult
7889683
493105.187500
2959668
Putem să creăm propria noastră funcție și s-o aplicăm asupra grupurilor.
def diff_min_max(x):
diff = x.max() - x.min()
return diff
grouped['rating'].agg([diff_min_max])
diff_min_max
genres
Childrens
0.24
Classics
0.97
Cultural
0.00
Fantasy
0.72
Fiction
0.68
Historical
0.34
Horror
0.34
Mystery
0.00
Nonfiction
0.55
Plays
0.00
Poetry
0.00
Romance
0.08
SciFi
0.14
Sequential Art
0.00
Unknown
0.53
Young Adult
0.89
Documentație: Group by
Series, Dataframe: map(), apply(), applymap()
books.head()
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213
1999
Unknown
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371
2004
Fiction
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215
2000
Romance
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32
2007
Childrens
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654
2003
Classics
books['page_count'].hist()

Vrem să categorizăm cărțile din setul nostru de date în cărți mici, medii și mari în dependență de numărul lor de pagini.
def eticheta(book):
if book <= 100:
return 'Small'
if 100 < book <= 500:
return 'Medium'
if book > 500:
return 'Large'
Putem să aplicăm asupra datelor o instrucțiune foarte specifică cu ajutorul metodei map()
, care aparține clasei Series.
# creăm o nouă coloană în setul de date books
books['book_size'] = books['page_count'].map(eticheta)
books.head()
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
book_size
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213
1999
Unknown
Medium
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371
2004
Fiction
Medium
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215
2000
Romance
Medium
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32
2007
Childrens
Small
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654
2003
Classics
Large
În cazul în care vrem să avem mai mulți parametri în funcția noastră vom utiliza metoda apply()
a clasei Series. Face același lucru ca și metoda map()
, doar că acceptă mai mulți parametri.
def eticheta_2(book, x, y):
if book <= x:
return 'Small'
if x < book <= y:
return 'Medium'
if book > y:
return 'Large'
books['review_count'].describe()
count 191.000000
mean 27694.921466
std 25972.632881
min 131.000000
25% 10632.500000
50% 19767.000000
75% 35001.500000
max 169961.000000
Name: review_count, dtype: float64
# creăm o coloană nouă în DataFrame-ul books.
books['review_number'] = books['review_count'].apply(eticheta_2, x=10632, y=35001)
books.head()
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
book_size
review_number
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213
1999
Unknown
Medium
Large
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371
2004
Fiction
Medium
Large
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215
2000
Romance
Medium
Medium
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32
2007
Childrens
Small
Small
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654
2003
Classics
Large
Medium
Mai jos avem o funcție care va transforma toate datele din coloană în procentaje față de valoarea maximă din aceeași coloană.
def scaling(valoare, col):
scaled_val = valoare/books[col].max()*100
return scaled_val
# creăm o coloană nouă în DataFrame-ul books
books['score%'] = books['score'].apply(scaling, col='score')
books.head()
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
book_size
review_number
score%
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213
1999
Unknown
Medium
Large
25.190562
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371
2004
Fiction
Medium
Large
14.448614
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215
2000
Romance
Medium
Medium
3.517050
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32
2007
Childrens
Small
Small
3.158733
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654
2003
Classics
Large
Medium
6.790052
# creați o coloana care arată procentajul valorilor din rating_count față de valoarea maxima din rating_count
books['rating_count%'] = books['rating_count'].apply(scaling, col = 'rating_count')
books.head()
id
name
authour
score
rating
rating_count
review_count
page_count
year
genres
book_size
review_number
score%
rating_count%
0
22628
The Perks of Being a Wallflower
Stephen Chbosky
745557
4.20
1219410
56409
213
1999
Unknown
Medium
Large
25.190562
17.908802
1
77203
The Kite Runner
Khaled Hosseini
427631
4.30
2365531
72036
371
2004
Fiction
Medium
Large
14.448614
34.741250
2
35545737
A Walk to Remember
Nicholas Sparks
104093
4.18
658664
12918
215
2000
Romance
Medium
Medium
3.517050
9.673435
3
32929
Goodnight Moon
Margaret Wise Brown
93488
4.28
296501
5729
32
2007
Childrens
Small
Small
3.158733
4.354547
4
153747
Moby-Dick or, the Whale
Herman Melville
200963
3.50
470744
15149
654
2003
Classics
Large
Medium
6.790052
6.913558
col = ['score%', 'rating_count%']
books[col].describe()
# observați cum selectăm doar 2 coloane din DataFrame-ul books
score%
rating_count%
count
191.000000
191.000000
mean
12.524109
14.546617
std
14.346202
14.907528
min
2.407534
0.123175
25%
3.556919
4.953056
50%
6.923243
9.515218
75%
16.792373
18.754470
max
100.000000
100.000000
def eticheta_3(book):
if book <= 5:
return 'Small'
if 5 < book <= 20:
return 'Medium'
if book > 20:
return 'Large'
Pentru a putea aplica o funcție specifică asupra mai multor coloane vom folosi metoda applymap()
care aparține clasei Dataframe.
transformed_col = books[['score%', 'rating_count%']].applymap(eticheta_3)
transformed_col
score%
rating_count%
0
Large
Medium
1
Medium
Large
2
Small
Medium
3
Small
Small
4
Medium
Medium
...
...
...
195
Medium
Medium
196
Small
Small
197
Small
Medium
198
Large
Medium
199
Medium
Medium
191 rows × 2 columns
Clasa DataFrame la fel are o metodă apply()
care transformă datele pe o axă fie că e Axa 1 sau Axa 0(column-wise, row-wise) a unui DataFrame, spre deosebire de celelalte metode: Series.map()
, Series.apply()
și DataFrame.applymap()
care transformă element cu element(elemnt-wise).
# Acum vom calcula câte valori de Small, Medium și Large avem în transformed_col
transformed_col.apply(pd.value_counts)
score%
rating_count%
Large
40
43
Medium
67
99
Small
84
49
pandas.concat()
Funcția concat() concatenează 2 tabele pe axa 0 sau pe axa 1.
Axis 0 - verticală. (implicit)
df1 = pd.DataFrame([[1, 'Marc', 9],[2, 'Mioara', 10],[3, 'Maxim', 7]], columns = ['id','elev', 'nota'])
df1
id
elev
nota
0
1
Marc
9
1
2
Mioara
10
2
3
Maxim
7
df2 = pd.DataFrame([[4, 'Monica', 7],[5, 'Maxim', 9],[6, 'Maia', 8]], columns = ['id','elev', 'nota'])
df2
id
elev
nota
0
4
Monica
7
1
5
Maxim
9
2
6
Maia
8
elevi = pd.concat([df1, df2], ignore_index=True)
elevi
id
elev
nota
0
1
Marc
9
1
2
Mioara
10
2
3
Maxim
7
3
4
Monica
7
4
5
Maxim
9
5
6
Maia
8
Axis 1 - orizontală
materii = pd.DataFrame([['Matematica', 5], ['L.Romana', 7], ['Informatica', 6], ['Desen', 9], ['Fizica', 7], ['Istorie', 10]],
columns = ['materie', 'clasa'])
materii
materie
clasa
0
Matematica
5
1
L.Romana
7
2
Informatica
6
3
Desen
9
4
Fizica
7
5
Istorie
10
situatia_scolara = pd.concat([elevi, materii], axis=1)
situatia_scolara
id
elev
nota
materie
clasa
0
1
Marc
9
Matematica
5
1
2
Mioara
10
L.Romana
7
2
3
Maxim
7
Informatica
6
3
4
Monica
7
Desen
9
4
5
Maxim
9
Fizica
7
5
6
Maia
8
Istorie
10
Ce s-ar fi întâmplat dacă în tabelul materii
ar mai fi existat un rând?
# Concatenați tabelul books cu tabelul transformed_col
new_tabel = pd.concat([books, transformed_col], axis=1)
new_tabel.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 191 entries, 0 to 199
Data columns (total 16 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 191 non-null int64
1 name 191 non-null object
2 authour 191 non-null object
3 score 191 non-null int64
4 rating 191 non-null float64
5 rating_count 191 non-null int64
6 review_count 191 non-null int64
7 page_count 191 non-null int64
8 year 191 non-null int64
9 genres 191 non-null object
10 book_size 191 non-null object
11 review_number 191 non-null object
12 score% 191 non-null float64
13 rating_count% 191 non-null float64
14 score% 191 non-null object
15 rating_count% 191 non-null object
dtypes: float64(3), int64(6), object(7)
memory usage: 30.4+ KB
pandas.merge()
absente = pd.DataFrame([[3, 'Maxim', 30], [6, 'Maia', 0], [2, 'Mioara', 57], [1, 'Marc', 124], [5, 'Maxim', 0], [7, 'Marica', 21]], columns=['id', 'nume', 'absente'])
absente
id
nume
absente
0
3
Maxim
30
1
6
Maia
0
2
2
Mioara
57
3
1
Marc
124
4
5
Maxim
0
5
7
Marica
21
pd.merge(left = situatia_scolara, right = absente, left_on = 'elev', right_on = 'nume', how = 'left')
# ce s-a întâmplat în tabelul de mai jos?
# de ce sunt mai multe rânduri?
id_x
elev
nota
materie
clasa
id_y
nume
absente
0
1
Marc
9
Matematica
5
1.0
Marc
124.0
1
2
Mioara
10
L.Romana
7
2.0
Mioara
57.0
2
3
Maxim
7
Informatica
6
3.0
Maxim
30.0
3
3
Maxim
7
Informatica
6
5.0
Maxim
0.0
4
4
Monica
7
Desen
9
NaN
NaN
NaN
5
5
Maxim
9
Fizica
7
3.0
Maxim
30.0
6
5
Maxim
9
Fizica
7
5.0
Maxim
0.0
7
6
Maia
8
Istorie
10
6.0
Maia
0.0
pd.merge(left = situatia_scolara, right = absente, on = 'id', how = 'left')
id
elev
nota
materie
clasa
nume
absente
0
1
Marc
9
Matematica
5
Marc
124.0
1
2
Mioara
10
L.Romana
7
Mioara
57.0
2
3
Maxim
7
Informatica
6
Maxim
30.0
3
4
Monica
7
Desen
9
NaN
NaN
4
5
Maxim
9
Fizica
7
Maxim
0.0
5
6
Maia
8
Istorie
10
Maia
0.0
# Uniți cele doua tabele: situatia_scolara și absențe folosind intersecția 'right'
# Uniți cele două tabele: situatia_scolara și absențe folosind intersecția 'inner'
# Uniți cele două tabele: situatia_scolara și absențe folosind intersecția 'outer'
Ce observați?
Seaborn
Seaborn este o librărie a lui Python, de vizualizare bazată pe Matplotlib. Această librărie oferă grafice cu stiluri predefinite.
import seaborn as sns
sns.set(style="ticks")
sns.pairplot(books, hue="book_size")

Accesând acest link puteți găsi galeria de grafice Seaborn și codul lor de implementare: Seaborn
Last updated