7. Indeksimi dhe transpozimi i një tabele

Në këtë leksion ne demonstrojmë:

  1. si indeksimi i një tabele siguron një qasje fleksibël në elementet e tabelës;
  2. si të llogariten nëpër rreshta dhe kolona të tabelës; dhe
  3. si të zhvendoset një tabelë.

7.1. Indeksimi

Ne kemi parë që të punosh me kolonat e një DataFrame është shumë e lehtë sepse kolonat kanë emra. Do të ishte aq e thjeshtë për të punuar me rreshtat e një DataFrame nëse do të kishim një mënyrë për t'i emëruar rreshtat në një farë mënyre. Procesi që bën saktësisht që quhet indeksimi i një tabele.

Për të indeksuar një tabelë, së pari duhet të identifikojmë një kolonë (kolonën e indeksimit ose indeksin) në mënyrë që çdo rresht në përcaktohet në mënyrë unike sipas vlerës në kolonën e indeksimit. Për shembull, në tabelën vijuese

Name Sex Age (yrs) Weight (kg) Height (cm)
Anne f 13 46 160
Ben m 14 52 165
Colin m 13 47 157
Diana f 15 54 165
Ethan m 15 56 163
Fred m 13 45 159
Gloria f 14 49 161
Hellen f 15 52 164
Ian m 15 57 167
Jane f 13 45 158
Kate f 14 51 162

"Name" është një kandidat i mirë për kolonën e indeksimit sepse në këtë tabelë studenti i gjërë ka një emër unik (vini re se në jetën reale kjo nuk është rastësisht). "Height" nuk është një zgjedhje e mirë sepse janë dy studentë, lartësia e të cilëve është 165; dhe e njëjta vlen edhe për kolonat e tjera.

Funksioni set_index vendos kolonën e indeksit të tabelës:

In [1]:
import pandas as pd
students = [["Anne",    "f", 13, 46, 160],
            ["Ben",     "m", 14, 52, 165],
            ["Colin",   "m", 13, 47, 157],
            ["Diana",   "f", 15, 54, 165],
            ["Ethan",   "m", 15, 56, 163],
            ["Fred",    "m", 13, 45, 159],
            ["Gloria",  "f", 14, 49, 161],
            ["Hellen",  "f", 15, 52, 164],
            ["Ian",     "m", 15, 57, 167],
            ["Jane",    "f", 13, 45, 158],
            ["Kate",    "f", 14, 51, 162]]
students_df = pd.DataFrame(students)
students_df.columns=["Name", "Sex", "Age", "Weight", "Height"]

students_ix=students_df.set_index("Name")

Tabela e re (students_ix) ndryshon nga ajo e vjetra (students_df) vetëm në faktin se rreshtat e tabelës tani janë indeksuar nga emrat e studentëve. Këtu është versioni i paindeksuar i tabelës:

In [2]:
students_df
Out[2]:
Name Sex Age Weight Height
0 Anne f 13 46 160
1 Ben m 14 52 165
2 Colin m 13 47 157
3 Diana f 15 54 165
4 Ethan m 15 56 163
5 Fred m 13 45 159
6 Gloria f 14 49 161
7 Hellen f 15 52 164
8 Ian m 15 57 167
9 Jane f 13 45 158
10 Kate f 14 51 162

dhe këtu është versioni i indeksuar i së njëjtës tabelë:

In [3]:
students_ix
Out[3]:
Sex Age Weight Height
Name
Anne f 13 46 160
Ben m 14 52 165
Colin m 13 47 157
Diana f 15 54 165
Ethan m 15 56 163
Fred m 13 45 159
Gloria f 14 49 161
Hellen f 15 52 164
Ian m 15 57 167
Jane f 13 45 158
Kate f 14 51 162

Kolona "Name" është ende e pranishme, por tani ajo ka një statis të veçantë. Nëse përpiqemi t'i qasemi asaj siç kemi bërë përpara se të kemi një gabim (raporti i gabimit është mjaft i gjatë; mos u shqetësoni ta lexoni me kujdes, thjesht lëvizni poshtë):

In [4]:
students_ix["Name"]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in get_loc(self, key, method, tolerance)
   3077             try:
-> 3078                 return self._engine.get_loc(key)
   3079             except KeyError:

pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: 'Name'

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
<ipython-input-4-475864f81b1d> in <module>
----> 1 students_ix["Name"]

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py in __getitem__(self, key)
   2686             return self._getitem_multilevel(key)
   2687         else:
-> 2688             return self._getitem_column(key)
   2689 
   2690     def _getitem_column(self, key):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py in _getitem_column(self, key)
   2693         # get column
   2694         if self.columns.is_unique:
-> 2695             return self._get_item_cache(key)
   2696 
   2697         # duplicate columns & possible reduce dimensionality

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\generic.py in _get_item_cache(self, item)
   2487         res = cache.get(item)
   2488         if res is None:
-> 2489             values = self._data.get(item)
   2490             res = self._box_item_values(item, values)
   2491             cache[item] = res

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals.py in get(self, item, fastpath)
   4113 
   4114             if not isna(item):
-> 4115                 loc = self.items.get_loc(item)
   4116             else:
   4117                 indexer = np.arange(len(self.items))[isna(self.items)]

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in get_loc(self, key, method, tolerance)
   3078                 return self._engine.get_loc(key)
   3079             except KeyError:
-> 3080                 return self._engine.get_loc(self._maybe_cast_indexer(key))
   3081 
   3082         indexer = self.get_indexer([key], method=method, tolerance=tolerance)

pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: 'Name'

Gjithsesi, ka një kolonë të indeksuar:

In [5]:
students_ix.index
Out[5]:
Index(['Anne', 'Ben', 'Colin', 'Diana', 'Ethan', 'Fred', 'Gloria', 'Hellen',
       'Ian', 'Jane', 'Kate'],
      dtype='object', name='Name')

Vizualisht, të themi, gjatësia e studentëve në grup tani llogaritet kështu:

In [6]:
import matplotlib.pyplot as plt
plt.figure(figsize=(10,5))
plt.bar(students_ix.index, students_ix["Height"])
plt.title("The height of students")
plt.show()
plt.close()
<Figure size 1000x500 with 1 Axes>

7.2. Qasja në rreshta dhe qeliza individuale të një tabele të indeksuar

DataFrame është optimizuar për të siguruar qasje efikase në kolonat e tabelës. Sidoqoftë, në një DataFrame të indeksuar është gjithashtu e lehtë për të hyrë në rreshta dhe qeliza të tabelës duke përdorur funksionin loc (shkurt për "vendndodhjen").

Ne mund të shfaqim një rresht të vetëm të tabelës si kjo:

In [7]:
students_ix.loc["Ethan"]
Out[7]:
Sex         m
Age        15
Weight     56
Height    163
Name: Ethan, dtype: object

ose disa rreshta si:

In [8]:
students_ix.loc["Ethan":"Ian"]
Out[8]:
Sex Age Weight Height
Name
Ethan m 15 56 163
Fred m 13 45 159
Gloria f 14 49 161
Hellen f 15 52 164
Ian m 15 57 167

Ne gjithashtu mund të përqëndrohemi në një veçori të veçantë:

In [9]:
students_ix.loc["Ethan", "Height"]
Out[9]:
163

ose shfaq një sërë karakteristikash për një seri rreshtash:

In [10]:
students_ix.loc["Ethan":"Ian", "Weight":"Height"]
Out[10]:
Weight Height
Name
Ethan 56 163
Fred 45 159
Gloria 49 161
Hellen 52 164
Ian 57 167

7.3. Llogaritja nëpër rreshta dhe kolona të një tabele të indeksuar

Në tabelën më poshtë kemi mbledhur notat e studentëve që kemi takuar tashmë në disa lëndë (Computers, English, Maths, Physics, Chemistry and Arts):

In [11]:
marks = [["Anne",    5, 3, 5, 2, 4, 5],
         ["Ben",     5, 5, 5, 5, 5, 5],
         ["Colin",   4, 5, 3, 4, 5, 4],
         ["Diana",   5, 5, 5, 5, 5, 5],
         ["Ethan",   3, 4, 2, 3, 3, 4],
         ["Fred",    4, 5, 3, 4, 5, 4],
         ["Gloria",  3, 3, 3, 4, 2, 3],
         ["Hellen",  5, 5, 4, 5, 4, 5],
         ["Ian",     4, 5, 4, 4, 3, 5],
         ["Jane",    2, 2, 2, 2, 2, 5],
         ["Kate",    3, 4, 5, 4, 5, 5]]

Le ta kthejmë në një DataFrame të indeskuar

In [12]:
marks_df = pd.DataFrame(marks)
marks_df.columns=["Name", "Computers", "English", "Maths", "Physics", "Chemistry", "Arts"]
marks_ix = marks_df.set_index("Name")
marks_ix
Out[12]:
Computers English Maths Physics Chemistry Arts
Name
Anne 5 3 5 2 4 5
Ben 5 5 5 5 5 5
Colin 4 5 3 4 5 4
Diana 5 5 5 5 5 5
Ethan 3 4 2 3 3 4
Fred 4 5 3 4 5 4
Gloria 3 3 3 4 2 3
Hellen 5 5 4 5 4 5
Ian 4 5 4 4 3 5
Jane 2 2 2 2 2 5
Kate 3 4 5 4 5 5

Llogaritja e notës mesatare për lëndë është e lehtë: ne thjesht aplikojmë mean për secilën kolonë të tabelës:

In [13]:
for subj in marks_ix.columns:
    print(subj, "->", round(marks_ix[subj].mean(), 2))
Computers -> 3.91
English -> 4.18
Maths -> 3.73
Physics -> 3.82
Chemistry -> 3.91
Arts -> 4.55

Për të llogaritur notën mesatare për student do të aplikojmë mean në rreshtat e tabelës, të cilave i aksesojmë duke përdorur loc. Si një stërvitje, le të llogarisim notën mesatare për Kate:

In [14]:
print("Kate's marks:")
print(marks_ix.loc["Kate"])
print("The average mark:", round(marks_ix.loc["Kate"].mean(), 2))
Kate's marks:
Computers    3
English      4
Maths        5
Physics      4
Chemistry    5
Arts         5
Name: Kate, dtype: int64
The average mark: 4.33

Emrat e të gjithë studentëve janë të vendosur në kolonën e indeksit, kështu që nota mesatare e secilit student në tabelë mund të llogaritet si kjo:

In [15]:
for student in marks_ix.index:
    print(student, "->", round(marks_ix.loc[student].mean(), 2))
Anne -> 4.0
Ben -> 5.0
Colin -> 4.17
Diana -> 5.0
Ethan -> 3.17
Fred -> 4.17
Gloria -> 3.0
Hellen -> 4.67
Ian -> 4.17
Jane -> 2.5
Kate -> 4.33

7.4. Transpozimi i një tabele

Transposing një tabelë është një operacion që këmbejnë rreshtat dhe kolonat e tabelës në mënyrë që rreshti i parë të shkëmbehet me kolonën e parë, rreshtat e dytë shkëmbehen me kolonën e dytë etj. Kur transpozoni një DataFrame të indeksuar, emrat e kolonave bëhen rreshti i indeksit të tabelës së re, ndërsa rreshti i indeksit jep emrat e kolonave në tabelën e re.

Transpose

Kujtoni që DataFrames janë optimizuar për qasje efikase në kolonat e tabelës. Prandaj, është e përshtatshme për të transpozuar një tabelë e cila ka disa rreshta shumë të gjatë. Për korrigjim, ne nuk kemi pse të imponojmë një tabelë që të jemi në gjendje të punojmë me të në mënyrë efikase (pasi 'loc' u jep mundësinë e përdorimit të rreshtave të tabelës), kështu që transpozimi i një tabelë është çështje shije ose komode.

Për të zhvendosur një tabelë thjesht aplikoni T për të marrë tabelën e re, të transpozuar. Për shembull, kujtoni që:

In [16]:
marks_ix
Out[16]:
Computers English Maths Physics Chemistry Arts
Name
Anne 5 3 5 2 4 5
Ben 5 5 5 5 5 5
Colin 4 5 3 4 5 4
Diana 5 5 5 5 5 5
Ethan 3 4 2 3 3 4
Fred 4 5 3 4 5 4
Gloria 3 3 3 4 2 3
Hellen 5 5 4 5 4 5
Ian 4 5 4 4 3 5
Jane 2 2 2 2 2 5
Kate 3 4 5 4 5 5

Pas transpozimit:

In [17]:
marks_tr = marks_ix.T

tabela e re duket kështu:

In [18]:
marks_tr
Out[18]:
Name Anne Ben Colin Diana Ethan Fred Gloria Hellen Ian Jane Kate
Computers 5 5 4 5 3 4 3 5 4 2 3
English 3 5 5 5 4 5 3 5 5 2 4
Maths 5 5 3 5 2 3 3 4 4 2 5
Physics 2 5 4 5 3 4 4 5 4 2 4
Chemistry 4 5 5 5 3 5 2 4 3 2 5
Arts 5 5 4 5 4 4 3 5 5 5 5

Le të kontrollojmë se çfarë ka ndodhur me index dhe columns. Në tabelën origjinale kemi:

In [19]:
marks_ix.index
Out[19]:
Index(['Anne', 'Ben', 'Colin', 'Diana', 'Ethan', 'Fred', 'Gloria', 'Hellen',
       'Ian', 'Jane', 'Kate'],
      dtype='object', name='Name')
In [20]:
marks_ix.columns
Out[20]:
Index(['Computers', 'English', 'Maths', 'Physics', 'Chemistry', 'Arts'], dtype='object')

ndërsa në tabelën e transpozuar kemi:

In [21]:
marks_tr.index
Out[21]:
Index(['Computers', 'English', 'Maths', 'Physics', 'Chemistry', 'Arts'], dtype='object')
In [22]:
marks_tr.columns
Out[22]:
Index(['Anne', 'Ben', 'Colin', 'Diana', 'Ethan', 'Fred', 'Gloria', 'Hellen',
       'Ian', 'Jane', 'Kate'],
      dtype='object', name='Name')

Siç kemi parë tashmë, nota mesatare për lëndë mund të llogaritet lehtë:

In [23]:
for subj in marks_ix.columns:
    print(subj, "->", round(marks_ix[subj].mean(), 2))
Computers -> 3.91
English -> 4.18
Maths -> 3.73
Physics -> 3.82
Chemistry -> 3.91
Arts -> 4.55

Për të llogaritur notat mesatare për secilin student, ne mund të përdorim loc për të hyrë në rreshtat e tabelës origjinale, por mund të bëjmë gjithashtu të njëjtën logjikë si më lart, por në tabelën e transpozuar:

In [24]:
for student in marks_tr.columns:
    print(student, "->", round(marks_tr[student].mean(), 2))
Anne -> 4.0
Ben -> 5.0
Colin -> 4.17
Diana -> 5.0
Ethan -> 3.17
Fred -> 4.17
Gloria -> 3.0
Hellen -> 4.67
Ian -> 4.17
Jane -> 2.5
Kate -> 4.33

7.5. Ushtrime

Ushtrimi 1. Shikoni me kujdes kodin më poshtë dhe pastaj përgjigjuni pyetjeve që vijojnë:

In [25]:
import pandas as pd
students = [["Anne",    "f", 13, 46, 160],
            ["Ben",     "m", 14, 52, 165],
            ["Colin",   "m", 13, 47, 157],
            ["Diana",   "f", 15, 54, 165],
            ["Ethan",   "m", 15, 56, 163],
            ["Fred",    "m", 13, 45, 159],
            ["Gloria",  "f", 14, 49, 161],
            ["Hellen",  "f", 15, 52, 164],
            ["Ian",     "m", 15, 57, 167],
            ["Jane",    "f", 13, 45, 158],
            ["Kate",    "f", 14, 51, 162]]
students_df = pd.DataFrame(students)
students_df.columns=["Name", "Sex", "Age", "Weight", "Height"]
students_ix=students_df.set_index("Name")

temp_anomalies = pd.read_csv("data/TempAnomalies.csv", header=None)
temp_anomalies_tr = temp_anomalies.T
temp_anomalies_tr.columns = ["Year", "Anomaly"]
  1. Cila është diferenca students_df dhe students_ix?
  2. Çfarë do të thotë students_ix.index?
  3. Sa është vlera e students_ix.loc["Fred"]?
  4. Sa është vlera e students_ix.loc["Fred", "Height"]?
  5. Sa është vlera e students_df.loc["Fred", "Height"]?
  6. Mund të aplikojmë T tek temp_anomalies?
  7. Sa kolona ka temp_anomalies_tr?

Ushtrimi 2. Kjo është një përmbledhje e shpenzimeve të një familjeje gjatë një viti (në monedhën vendase):

Item Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Rent 8,251 8,436 8,524 8,388 8,241 8,196 8,004 7,996 7,991 8,015 8,353 8,456
Electricity 4,321 4,530 4,115 3,990 3,985 3,726 3,351 3,289 3,295 3,485 3,826 3,834
Phone (landline) 1,425 1,538 1,623 1,489 1,521 1,485 1,491 1,399 1,467 1,531 1,410 1,385
Phone (cell) 2,181 2,235 2,073 1,951 1,989 1,945 3,017 2,638 2,171 1,831 1,926 1,833
TV and Internet 2,399 2,399 2,399 2,399 2,399 2,399 2,399 2,399 2,399 2,399 2,399 2,399
Transport 1,830 1,830 1,830 1,830 1,950 1,950 1,450 1,450 1,950 1,950 2,050 2,050
Food 23,250 23,780 24,019 24,117 24,389 24,571 24,736 24,951 25,111 25,389 25,531 25,923
Rest 4,500 3,700 5,100 3,500 2,750 4,250 7,320 8,250 3,270 4,290 3,200 8,390

Tabela e prezantuar si listë duket kështu:

In [26]:
spendings = [
  ["Rent", 8251, 8436, 8524, 8388, 8241, 8196, 8004, 7996, 7991, 8015, 8353, 8456],
  ["Electricity", 4321, 4530, 4115, 3990, 3985, 3726, 3351, 3289, 3295, 3485, 3826, 3834],
  ["Landline", 1425, 1538, 1623, 1489, 1521, 1485, 1491, 1399, 1467, 1531, 1410, 1385],
  ["Cell", 2181, 2235, 2073, 1951, 1989, 1945, 3017, 2638, 2171, 1831, 1926, 1833],
  ["TV and Internet", 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399, 2399 ],
  ["Transport", 1830, 1830, 1830, 1830, 1950, 1950, 1450, 1450, 1950, 1950, 2050, 2050],
  ["Food", 23250, 23780, 24019, 24117, 24389, 24571, 24736, 24951, 25111, 25389, 25531, 25923],
  ["Rest", 4500, 3700, 5100, 3500, 2750, 4250, 7320, 8250, 3270, 4290, 3200, 8390]
]

(a) Shndërroni këtë listë në një DataFrame dhe indeksoni atë.

(b) Llogaritni shpenzimet mesatare të kësaj familje për artikull (Rent, Electricity etj).

Ushtrimi 3. Pesë grupe studentësh morën pjesë në një sondazh studentor për zhanret e tyre të preferuar të filmit. Çdo studenti i lejohej të votonte saktësisht një zhanër. Rezultatet e sondazhit janë përmbledhur më poshtë:

Genre Group 1 Group 2 Group 3 Group 4 Group 5
Comedy 4 3 5 2 3
Horror 1 0 2 1 6
SF 10 7 9 8 9
Adventure 4 3 4 2 2
History 1 0 2 0 0
Romance 11 10 7 9 8

(a) Kthejeni këtë në një DataFrame të indeksuar nga zhanri.

(b) Llogaritni numrin e votave për zhanër.

(c) Për secilin grup llogaritni numrin e përgjithshëm të studentëve që morën pjesë në votime.

(d) Cili është numri i përgjithshëm i studentëve që morën pjesë në votime?

Ushtrimi 4. Të dhëna ushqyese për produkte të caktuara, të dhëna në tabelën më poshtë:

Product (100g) Nutritive value (kcal) Carbohydrates (g) Proteins (g) Fats (g)
Rye bread 250 48.2 8.4 1.0
White bread 280 57.5 6.8 0.5
Cheese spread 127 4.0 3.1 10.5
Margarin 532 4.6 3.2 1.5
Yoghurt 48 4.7 4.0 3.3
Milk (2.8%) 57 4.7 3.3 2.8
Salami 523 1.0 17.0 47.0
Ham 268 0.0 25.5 18.4
Chicken breast 110 0.0 23.1 1.2

Në qelizën më poshtë kemi shndërruar këtë tabelë në një DataFrame të indeksuar me emrin e produktit:

In [27]:
food = pd.DataFrame([
    ["R-bread", 250, 48.2, 8.4, 1.0],
    ["W-bread", 280, 57.5, 6.8, 0.5],
    ["Spread", 127, 4.0, 3.1, 10.5],
    ["Margarin", 532, 4.6, 3.2, 1.5],
    ["Yoghurt", 48, 4.7, 4.0, 3.3],
    ["Milk", 57, 4.7, 3.3, 2.8],
    ["Salami", 523, 1.0, 17.0, 47.0],
    ["Ham", 268, 0.0, 25.5, 18.4],
    ["ChBreast", 110, 0.0, 23.1, 1.2]])
food.columns=["Product", "NutrVal", "Carbs", "Proteins", "Fats"]
food_ix = food.set_index("Product")

(a) Për mëngjesin e tij Mike kishte dy copë bukë të bardhë dhe kishte një filxhan qumësht. Çdo copë bukë kishte përhapur disa djathë dhe një fetë proshutë. Cila është vlera ushqyese e mëngjesit të Mike (në kcal) nëse supozojmë se secila copë bukë peshon 100g, se për 10h përhapje është përdorur për një copë bukë, se një fetë proshutë peshon 20g dhe se një filxhan qumësht përmban 200 d e qumeshtit?

(b) Sa yndyrë ka pasur në mëngjesin e Mike?

(c) Vizualizoni sasinë e karbohidrateve në këto produkte.

Ushtrimi 5. Anomalia e temperaturës është një numër që na tregon se sa temperatura mesatare në një vit të veçantë devijon nga vlera optimale. Skeda TempAnomalies.csv e vendosur në dosjen data përmban anomalitë e temperaturës (në gradë Celsius) për periudhën prej 40 vjetësh (1977-2017). Dosja ka dy rreshta si kjo:

1977,1978,1979,1980,1981,...
0.22,0.14,0.15,0.3,0.37,...

(a) Vendosni tabelën në një DataFrame (Shënim: tabela nuk ka header, kështu që ju nevojitet opsioni header = Noneread_scv tuaj.)

In [ ]:

(b) Ndërroni tabelën dhe thërrsni dy kolonat "Year" dhe "Anomaly".

In [ ]:

(c) Indekso tabelën.

In [ ]:

(d) Vizualizoni anomalitë e temperaturës me një grafik vijash.

In [ ]:

© 2019 Petlja.org Creative Commons License