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)