A programozási nyelvek népszerűségének alakulása
Adatvizualizáció a Matplotlib segítségével
A programozási nyelvek fejlődése és népszerűsége izgalmas történet, amely rengeteg adattal szolgálhat a technológiai trendekről.
Ebben a cikkben lépésről lépésre bemutatom, hogyan használhatjuk a Python programozási nyelvet és a Pandas, valamint Matplotlib könyvtárakat a Stack Overflow posztok adatainak elemzése céljából.
A célunk az, hogy betekintést nyerjünk a nyelvek népszerűségének alakulásába, valamint kipróbáljunk néhány hasznos adatelemzési és -tisztítási technikát.
A feladatot lépésekben fogom bemutatni. A gyakorlat során a Google Colab Notebook szoftvert fogom használni, amely lényegében a Jupyter online verziója.
1. lépés: Adatfeltárás
Adjuk hozzá a “QueryResults.csv” fájlt a Notebook-hoz.
2. lépés
Importáljuk a Pandas könyvtárat a Notebookba, olvassuk be a .csv fájlt, és kezdjük el az adatok feltárását!
A Pandas egy nyílt forráskódú Python könyvtár, amelyet adatkezelésre és -elemzésre használnak. Különösen hasznos a strukturált adatokat (például táblázatos adatokat) kezelő feladatokhoz. Ezt a könyvtárat fogjuk most mi is használni.
import pandas as pd
df = pd.read_csv('QueryResults.csv', names=['DATE', 'TAG', 'POSTS'], header=0
3. lépés
Nézzünk rá a Pandas dataframe-re. A DataFrame a Pandas könyvtár egyik alapvető adatstruktúrája, amely táblázatos adatokat kezel. Képzeljük el úgy, mint egy Excel-táblázatot vagy egy adatbázis táblát: sorokból és oszlopokból áll. A .head() parancs pedig megjeleníti nekünk a DataFrame első 5 sorát.
df.head()
4. lépés
A .tail() parancs felfedi a DataFrame utolsó 5 sorát. Vessünk egy pillantást erre is. Így könnyen átnézhetjük az adatok végét, ha kíváncsiak vagyunk arra, hogy milyen információk találhatók az utolsó sorokban.
df.tail()
5. lépés
Ezután meg kell vizsgálnunk a DataFrame dimenzióit is. Ezt a .shape parancs segítségével tehetjük meg, ami megmondja nekünk, hogy hány sor és oszlop található az adathalmazban. Például, ha az eredmény (1991, 3), akkor az azt jelenti, hogy 1991 sor és 3 oszlop található a DataFrame-ben.
df.shape
6. lépés
Használjuk a .count() parancsot, hogy megszámoljuk az egyes oszlopokban található nem-NaN (nem hiányzó) értékeket. Ez segít abban, hogy lássuk, hány érvényes adat található az egyes oszlopokban, és hogy van-e bármilyen hiányzó érték az adatainkban.
df.count()
7. lépés
Hány hozzászólás kapcsolódik minden egyes programozási nyelvhez a Stack Overflow létrejötte óta?
df.groupby('TAG').sum()
8. lépés
Melyik programozási nyelv rendelkezik a legtöbb hozzászólással minden idők során?
df.sort_values('POSTS' , ascending=False)
9. lépés
Hány hónapnyi bejegyzés található programozási nyelvenként?
df.groupby('TAG').count()
10. lépés
Hány hónapnyi adat található programozási nyelvenként? Melyik nyelv rendelkezik a legkevesebb hónapnyi adattal, amiben szerepel bejegyzés?
df.groupby('TAG').count().sort_values(by='DATE', ascending=True)
9. lépés: Adattisztítás: Munkavégzés Időbélyegekkel
Nézzük meg közelebbről a ‘DATE’ oszlopot az adatkeretünkben.
df['DATE'][1]
Vagy így is írhatjuk:
df.DATE[1]
12. lépés
Javítsuk ki a dátum formátumát, hogy könnyebben olvasható legyen. Ehhez a Pandas könyvtárat fogjuk használni, hogy a ‘2008-08-01 00:00:00‘ szövegformátumot átalakítsuk egy olyan datetime objektummá, amely pl. ‘2008-07-01‘ formátumban jelenik meg.
Az adat típusának vizsgálata:
Ellenőrizzük ezeknak a celláknak a tartalmát, és látni fogjuk, hogy nem egy dátum objektummal van dolgunk, hanem egy szöveges karakterlánncal (string).
type(df['DATE'][1])
13. lépés
A Pandas to_datetime() metódus segítségével az egész oszlopban alakítsuk át időbélyeggé a szöveges karakterláncokat (string-eket).
df.DATE = pd.to_datetime(df.DATE)
df.head()
14. lépés
Futtassuk le újra az adattípus ellenőrzést, és látni fogjuk az adattípusok változását. Pl.: ellenőrizzük most a 115. sort.
type(df['DATE'][115])
15. lépés: Adatmódosítás: Adatkeretek pivotálása
Itt a .pivot() metódust fogjuk használni. Ez akkor hasznos, ha azt szeretnénk, hogy az adatkeret minden kategóriájának saját oszlopa legyen. Az indexek a sorok kategóriái, ahol az oszlopok a kategóriák. Az értékek pedig azok, amiket az új cellákba szeretnénk elhelyezni. Ha egy érték hiányzik, a .pivot() metódus NaN értéket fog beszúrni.
Pivotálhatjuk a df adatkeretet úgy, hogy minden sor egy dátumot, és minden oszlop egy programozási nyelvet reprezentáljon? Az eredményt egy reshaped_df nevű változóban tároljuk.
reshaped_df = df.pivot(index='DATE', columns='TAG', values='POSTS')
reshaped_df.head()
16. lépés
Hány sora és oszlopa van?
reshaped_df.shape
145 sor és 14 oszlop jelenik meg.
17. lépés
Nézzünk rá a DataFrame végére, és láthatjuk, hogyan néz ki.
reshaped_df.tail()
18. lépés
Amikor megszámoljuk az egyes oszlopok bejegyzéseit, látjuk, hogy nem minden programozási nyelv mutatja ugyanazt az értéket. Ennek oka, hogy a .count() metódus figyelmen kívül hagyja a NaN értékeket. Amikor pivotáltuk az adatkeretet, NaN értékek kerültek be, amikor egy adott hónapban nem voltak bejegyzések egy nyelvhez (például Swift 2008 júliusában).
reshaped_df.count())
19. lépés: NaN értékek kezelése
Mi most nem szeretnénk törölni azokat a sorokat, amelyek NaN értéket tartalmaznak. Helyette “0“-ra fogjuk őket cserélni. Ebben az esetben a fillna() metódust fogjuk használni.
reshaped_df = reshaped_df.fillna(0)
reshaped_df.head()
20. lépés
Az alábbi sorral azt is ellenőrizhetjük, hogy maradtak-e NaN értékek az egész adatkeretben. Itt a .isna() metódust használjuk, amit már korábban alkalmaztunk, de most két további dolgot adunk hozzá: az values attribútumot és az any() metódust. Ez azt jelenti, hogy nem kell végigkeresnünk az egész adatkeretben, hogy észrevegyük, ha a .isna() értéke “True“.
reshaped_df.isna().values.any()
21. lépés: Adatok vizualizálása a Matplotlib segítségével
A Matplotlib egy rendkívül népszerű könyvtár, és gyönyörűen működik a Pandas-szal kombinálva. Kezdetben a Matplotlib-ot importálni kell a kód elején.
reshaped_df.isna().values.any()
22. lépés: Az első diagramunk
A diagram létrehozásához csak annyit kell tennünk, hogy megadjuk az értékeket a vízszintes tengelyhez (x-értékek) és a függőleges tengelyhez (y-értékek). Az x-értékek a dátumok, az y-értékek pedig a bejegyzések száma. Ezen értékeket a .plot() függvénynek pozíció szerint adhatjuk át:
plt.plot(reshaped_df.index, reshaped_df.java)
Vagy használhatjuk a szögletes zárójel szintaxist is, az eredmény ugyanaz lesz:
plt.plot(reshaped_df.index, reshaped_df['java'])
23. lépés
Számos módszer áll rendelkezésünkre, amelyek segítenek a diagramunk formázásában:
# Lehetővé teszi számunkra, hogy átméretezzük a diagramot
.figure()
# Konfigurálja a vízszintes tengelyünket (x-tengely)
.xticks()
# Konfigurálja a függőleges tengelyünket (y-tengely).
.yticks()
# Szöveget adhatunk az x-tengelyhez
.xlabel()
# Szöveget adhatunk az y-tengelyhez
.ylabel()
# Lehetővé teszi számunkra, hogy alsó és felső határt állítsunk be
.ylim()
Növeljük meg egy kicsit a diagramunk méretét. Például beállíthatjuk a szélességet (16) – ra, a magasságot (10) -re a figure (figsize=(16, 10)) paraméterrel.
plt.figure(figsize=(16,10))
plt.plot(reshaped_df.index, reshaped_df.java)
24. lépés
Növelnünk kellene a tengelyeken lévő jelölések betűméretein is, hogy könnyen olvashatóak legyenek:
plt.figure(figsize=(16,10))
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.plot(reshaped_df.index, reshaped_df.java)
25. lépés
Adjunk hozzá címkéket. Mivel soha nem lesz kevesebb, mint 0 bejegyzésünk, állítsunk be egy alsó határt az y-tengelyen 0-ra.
plt.figure(figsize=(16,10))
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.xlabel('Date', fontsize=14)
plt.ylabel('Number os Posts', fontsize=14)
plt.ylim(0, 35000)
plt.plot(reshaped_df.index, reshaped_df.java)
26. lépés
Jelenítsük meg egymás mellett a Java-t és a Python-t:
plt.figure(figsize=(16,10)) # to make chart larger
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.xlabel('Date', fontsize=14)
plt.ylabel('Number os Posts', fontsize=14)
plt.ylim(0, 35000)
plt.plot(reshaped_df.index, reshaped_df.java, reshaped_df.python)
27. lépés
Tegyük fel, hogy szeretnénk az összes programozási nyelvet ugyanazon a diagramon ábrázolni. Ehhez egy for-ciklust használunk:
plt.figure(figsize=(16,10))
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.xlabel('Date', fontsize=14)
plt.ylabel('Number os Posts', fontsize=14)
plt.ylim(0, 35000)
# Using for loop, we can plot all languages
for column in reshaped_df.columns:
plt.plot(reshaped_df.index, reshaped_df[column])
28. lépés
a) Módosítsuk a kódot úgy, hogy minden görbéhez címkét adunk hozzá, az oszlop neve alapján.
b) Tegyük vastagabbá a vonalakat a linewidth paraméterrel.
c) Ezután adjunk hozzá egy jelmagyarázatot a diagramunkhoz.
plt.figure(figsize=(16,10))
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.xlabel('Date', fontsize=14)
plt.ylabel('Number os Posts', fontsize=14)
plt.ylim(0, 35000)
for column in reshaped_df.columns:
plt.plot(reshaped_df.index, reshaped_df[column],
linewidth=3, label=reshaped_df[column].name)
plt.legend(fontsize=16)
Úgy tűnik, hogy a Python foglalja el az első helyet, mint a legszélesebb körben használt programozási nyelv, ha a Stack Overflow bejegyzések bőségét vesszük alapul!
29. lépés
Figyeljük meg, hogy a görbék jelentős ingadozásokat mutatnak, ami “zajossá” és nehezen érthetővé teszi az ábránkat.
Ahhoz, hogy a trend jobban észrevehető legyen, egy hasznos módszer az adatok túlzott ingadozására, még pedig egy átlag kiszámítása. Ha például 6 vagy a 12 megfigyelésre átlagolunk, létrehozhatunk egy úgynevezett görgetett átlagot (rolling mean). Ez lényegében azt jelenti, hogy egy időablakban átlagot számítunk, majd az ablakot egyesével előre toljuk.
Ez a technika annyira elterjedt, hogy a Pandas két kényelmesen használható beépített módszert is kínál hozzá: a rolling() és a mean() metódusokat. E két módszer összefűzésével könnyedén létrehozhatunk egy DataFrame-et, amely kissé “kisímítja” az ingadozó diagramunkat.
# The window represents the number of observations that are averaged together
roll_df = reshaped_df.rolling(window=6).mean()
plt.figure(figsize=(16,10))
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.xlabel('Date', fontsize=14)
plt.ylabel('Number os Posts', fontsize=14)
plt.ylim(0, 35000)
for column in roll_df.columns:
plt.plot(roll_df.index, roll_df[column],
linewidth=3, label=roll_df[column].name)
plt.legend(fontsize=16)