☠ 9. feladat

Mekegünk vagy nem mekegünk?

Gyakran mondják, hogy a magyar nyelv aránytalanul sok e-betűt használ, idegen hallgatóság úgy érzékeli, mintha sokat "mekegnénk".

  • Vizsgáljuk meg, mi a 10 leggyakoribb magyar betű Mikszáth Kálmán A fekete város c. regényében (data/fekete_varos.txt)!
  • Figyeljünk arra, hogy számlálás közben mindent kisbetűssé alakítsunk.
  • Benne van-e az első 10 betű között az "e"?
  • A két- és háromjegyű mássalhangzókat most kezeljük két külön betűnek.

Megoldás

Betöltjük a szükséges csomagot

In [1]:
%pylab inline
Populating the interactive namespace from numpy and matplotlib

Létrehozunk egy szótárat, amiben a magyar betűk előfordulását számoljuk a szövegben. Nyilván, mindegyik 0-ról indul

In [2]:
betuk = {'a':0, 'á':0, 'b':0, 'c':0, 'd':0, 'e':0, 'é':0, 'f':0, 'g':0, 'h':0, 'i':0, 'í':0,
         'j':0, 'k':0, 'l':0, 'm':0, 'n':0, 'o':0, 'ó':0, 'ö':0, 'ő':0, 'p':0, 'q':0, 'r':0,
         's':0, 't':0, 'u':0, 'ú':0, 'ü':0, 'ű':0, 'v':0, 'w':0, 'x':0, 'y':0, 'z':0}

Ezután betöltjük a fájlt, és egyesével végiglépkedünk a karakterein, és minden betű előfordulása után a szótárban hozzárendelt számot eggyel megnöveljük.

In [3]:
with open("../data/fekete_varos.txt") as f:
    karakter = f.read(1)              # Egyesével beolvassuk
    while karakter != "":             # Addig futtatjuk a programot, amíg a beolvasott karakter nem lesz üres
        if karakter.lower() in betuk: # Ha a beolvasott karakter betű, akkor ezt rögzítjük
            betuk[karakter.lower()] +=1
        karakter = f.read(1)

Eztuán kiíratjuk az első 10 leggyakoribb betűt, és láthatjuk, hogy nemcsak hogy benne van az e, de ez szerepel e szedet legtetején (megjegyzem, nem lep meg).

In [4]:
sorted(betuk.items(), key=lambda x:x[1], reverse=True)[:10]
Out[4]:
[('e', 72183),
 ('a', 62971),
 ('t', 56582),
 ('n', 42377),
 ('l', 40973),
 ('s', 39889),
 ('k', 32873),
 ('o', 30183),
 ('i', 28169),
 ('r', 28074)]

Zipf-eloszlás

Mivel a kiírt feladat megoldása nem volt hosszú, és már egy ideje foglalkoztat egy másik, nyelv-statisztikai kérdés, ezt is megvizsgálom. A Zipf-eloszlás szerint egy nyelvben egy adott szó gyakorisága fordítottan arányos azzal, hogy hányadik leggyakrabban használt szó az az adott nyelvben. Ennek megvizsgálásához elkészítem ezt a statisztikát a Fekete városra.

Ehhez, létre kell hoznunk egy másik szótárat, amiben majd a szavakt fogjuktárolni, de ezt nem tudjuk előre feltölteni, hanem csak a később talált szavakat rakjuk bele. A fájlt ugyanúgy karakterenként olvassuk be, mint az előző feladatrészbe, de most nem egyesével, hanem szavanként adjuk hozzá a szótárhoz. Egy szónak akkor van vége, ha egy vagy több betű után beolvasunk egy nem-betű karaktert.

In [5]:
szavak = dict()
with open("../data/fekete_varos.txt") as f:
    szo = ""
    karakter = f.read(1) # Egyenkénti beolvasás
    while karakter != "": # Addig amíg a beolvasott karakter üres karakter nem lesz
        if karakter.lower() in betuk: # Ha a beolvasott karakter betű, hozzáadjuk az aktuális szóhoz
            szo += karakter.lower() 
        elif szo != "": # Ha nem, akkor az aktuális szót hozzáadjuk a szótárhoz, és a szo változót "lenullázzuk"
            if szo in szavak:
                szavak[szo] += 1
            else:
                szavak[szo] = 1
            szo = ""
        karakter = f.read(1)

Eztuán a szavak szótár adatait sorbarendezzük, és ábrázoljuk az előfordulás gyakoriságának sorrendje szerint.

In [6]:
lista = sorted(szavak.items(), key=lambda x:x[1], reverse=True)
y = zeros(len(lista))
for i in range(len(lista)):
    y[i] = lista[i][1]
    
plot(range(len(lista)), y)
loglog()
title("A szavak gyakorisága a szövegben", size=18, y =1.05)
xlabel("A gyakoriság rangja", size=12)
ylabel("Az elöfordulások száma")
Out[6]:
<matplotlib.text.Text at 0x7f1714a0c470>

Nyilvánvalóan a legtöbbször és a legritkábban előforduló szavak valamennyire torzítják a statisztikát, de a többi adat a logaritmikus skálán egy -1 meredekségű egyenest rajzol ki, láthatjuk, valóban jól leírja a Zipf-eloszlás a szavak előfordulását (legalább a Fekete városban).