Labádi Gergely </filológia>

Távoli olvasó olvas

Bevezetés a bevezetésbe

Az utóbbi időben igyekeztem elmélyülni a distant reading elméletében és gyakorlatában. Az elmélet megismerése a szokásos utakon-módokon zajlik. Könyvek, tanulmányok különböző szerzők elolvasása, kijegyzetelése. Aztán cikkek, recenziók írása, előadások, szemináriumok tartása… Ja igen, néha töprengeni, mélázni sem árt a kijegyzetteken, elmondottakon. Szóval ahogy a bölcsészek csinálják.

A gyakorlat… Nyilván már egy excell-táblázat is alkalmas erre, de azért vannak ennél kifinomultabb és hajlékonyabb, illetve alkalmasabb eszközök. Még én is tanulom őket. Docendo discimus. Persze magamat tanítom – végtelen hurok.

Belevágni egyszerű: különösebb felkészülés nélkül is elő lehet venni Maciej Eder, Jan Rybicki és Mike Kestemont programcsomagját, a stylo-t. Persze telepíteni kell hozzá az R-t Erről nem írok, elég jó dokumentációja van, vannak tanulmányok is mellé. Stilometriára lehet használni. A stilometriának ugyanakkor nemcsak a szerzőségattribúcióban van jelentősége, vannak további lehetőségei – erről többen hosszabban írtak: Matthew L. Jockers vagy éppen a Distant readings tanulmányai – érdemes az utóbbiak magyarázatait hozzáolvasni, mert közérthetően mondják el, hogy az egyes beállítások mire jók. Magyar szövegeket is kezel, van beépített magyar stopszólistája is. A szövegeknek .txt vagy .xml formátumban kell lenniük.

De ha magunk akarunk távolról olvasni, akkor érdemes belevetni magunkat az R használatába. Nekem Matthew Jockers könyve volt az útmutató. Az ő példáit alkalmazom, módosításokkal – persze most még sok sziporka nem lesz. Mondjuk ilyen „műalkotásokat” tudunk majd csinálni a „lecke” végén: Az arany ember írásjelei – nem mintha ez volna a distant reading lényege… aeirasjel

1. Előfeltételek

Ebben a leírásban adottnak veszem, hogy telepítve van az R és az RStudio. Nem fogom elmagyarázni az egyes R-adattípusokat (data.frame, list, character stb.), ebben a részben nincs is rá szükség. Továbbá le kell még tölteni egy egyszerű java-programot is, a magyarlanc-ot.

2. Szövegelőkészítés

A magyarlanc egy java-program, amelyet a SZTE és az MTA Mesterséges Intelligencia Kutatócsoportja készített. Ingyen letölthető, de szükséges, hogy a java8 telepítve legyen. Általában fent van a gépeken. Morfológiai elemzést készít.

2.1. A magyarlanc használata

  • Miután letöltöttük, az egyszerűség kedvéért érdemes abba a könyvtárba másolni, amelyikben a feldolgozandó fájlunk van.
  • Be kell hívni a parancssort/terminált és át kell menni abba a könyvtárba, ahol a magyarlanc található. (Ha valaki elfelejtette volna, a cd paranccsal [change directory] lehet könyvtárat váltani.)
  • A szövegnek .txt formátumban kell lennie. A [magyarlanc] 19. századi szövegekkel is jól elbodogul, de pontosabb lesz, ha sztenderdizálva van a szöveg. Tehát a ts, tz, cz és társaikat normalizálni érdemes.
  • A futtatás egyszerű, gépeljük/másoljuk be a következő parancsot:
java -Xmx1G -jar magyarlanc-3.0.jar -mode morphparse -input in.txt -output out.txt
  • A magyarlanc honlapján van egy részletesebb leírás arról, hogy milyen opciókat lehet bekapcsolni – én a morphparse-ot szoktam használni.
  • Az in.txt helyén értelemszerűen a feldolgozandó szövegfájlunk neve álljon. Valójában nem kell egy könyvtárban lennie a magyarlanc-nak a fájllal, de akkor a magyarlanc felőli elérési utat is meg kell adni az in.txt helyén.
  • Az out.txt a kimeneti fájl. Természetesen az elérési utat és nevet is lehet módosítani.
  • Így néz ki Az arany ember eleje a magyarlanc-cal elemezve:

Az arany ember elemzése

  • Négy oszlopot tartalmaz, amelyeket tabulátor választ el. Az első az eredeti szöveg. A második a lemmatizált (szótári) szóalak. A harmadik a szófaj*. A negyedik a morfológiai elemzés.

2.2. Beolvasás az R-be

  • Miután megnyitottuk az RStudio-t, állítsuk be a munkakönyvtárat.
    • Az aktuális munkakönyvtárat a getwd() paranccsal lehet lekérdezni.
    • Munkakönyvtárat beállítani a setwd("konyvtareleresiutja") paranccsal lehet vagy a Session menü Set Working Directory alpontjában.

2.2.1. A magyarlanc-cal feldolgozott fájl betöltése

valtozo.df <- read.csv2(file = "out.txt", header = FALSE, sep = "\t", stringsAsFactors = FALSE)
  • Egy valtozo.df nevű data.frame-be (praktikusan: táblázat) olvassuk be a fájlt (a <- helyett használhatunk =-t is).
  • Az első argumentum a fájl elérési útja és neve (jelen esetben a fájl a munkakönyvtárban van).
  • A másodikkal azt mondjuk, hogy az első sort ne tekintse fejlécnek.
  • A harmadikkal, hogy az elemeket tabulátor választja el (egy “rendes” .csv esetében ","-t kel írni, mivel vessző a választóelem [comma separated values]).
  • A negyedikkel, hogy az azonos alakokat ne ejtse ki, hanem mindet tartsa meg. Az R alapesetben ugyanis az ismétlődő alakokat kiejtené.

2.2.2. Egy nem feldolgozott fájl betöltése

  • Természetesen nemcsak a magyarlanc-cal előkészített fájlt lehet beolvasni, magát az eredeti fájlt is importálhatjuk. Mivel mint rövidesen látni fogjuk, az előkészített fájlból bármelyik oszlop tartalmát kinyerhetjük, ezért az eredeti és a lemmatizált szöveg is rendelkezésünkre áll. Ugyanakkor egy hátránya van az így előkészített fájlnak: az eredeti bekezdés- és fejezetstruktúráját nem tudjuk reprodukálni, azaz nem tudjuk az elemzés szempontjává tenni. Tehát ha erre lesz szükségünk, akkor máshogy kell a fájlt importálni:
aranyember.v <- scan("aranyember_kritikai.txt", what="character", sep="\n")
  • Az első argumentum az importálandó fájlnév. Ha nincs külön elérési út megadva, akkor a munkakönyvtárban kell lennie a fájlnak.
  • A második argumentum azt jelzi, hogy a fájl tartalma karaktervektorként importálandó.
  • A harmadik azt az utasítást adja, hogy a fájl tartalmát new line elemenként, azaz bekezdésenként tárolja el.

2.3. Alapműveletek – legalábbis néhány

2.3.1. Terjedelem lekérdezése

  • Ha lekérdezzük, kiderül, hogy Az arany ember-t tartalmazó fájlunknak 179705 sora és 5 oszlopa van. A karaktervektorokét máshogy kérdezzük le (length(x)), lásd a 3. pontnál.
> dim(valtozo.df)
[1] 179705      5

2.3.2. Elemek eltávolítása

  • Ha kiíratjuk a változó elejét, akkor látjuk, hogy az ötödik oszlop valójában üres (a példában a > az RStudio konzolján látszik, nem kell begépelni). Ezt akár törölhetjük is. Utána ellenőrizzük! (Ez utóbbit már nem írtam bele a példába!)
> head(valtozo.df, n = 5)
       V1      V2   V3                               V4 V5
1       A       a  DET        Definite=Def|PronType=Art NA
2   SZENT   szent  ADJ  Case=Nom|Degree=Pos|Number=Sing NA
3 BORBÁLA borbála NOUN             Case=Nom|Number=Sing NA
4      I.      1.  ADJ Case=Nom|NumType=Ord|Number=Sing NA
5       A       a  DET        Definite=Def|PronType=Art NA
> valtozo.df$V5 = NULL

2.3.3. Elemek exportálása

  • A változóból bármelyik oszlopot (és sort) exportálni lehet, hogy további elemzéseknek vessük alá (pl. ha a szófajok érdekelnek, vagy ha mondjuk később a morfológiai elemzések [mennyi jelen idejű ige van és mennyi múlt idejű…]). A következő két parancs a lemmatizált alakokat teszi egy egyoszlopos data.frame-be (mindegy, melyiket használjuk):
lemma.valtozo.df = valtozo.df[2]
lemma.valtozo.df = valtozo.df["V2"]
  • Ellenőrizzük, hogy az új változónak (lemma.valtozo.df) hány sora és oszlopa van!
  • A data.frame típusú adatból karaktervektort is csinálhatunk. Utána ellenőrizzük a hosszúságát, és kiíratjuk az első 5 elemét:
> szoveg.v = unlist(lemma.valtozo.df, use.names = FALSE)
> length(szoveg.v)
[1] 179705
> head(szoveg.v, n = 5)
[1] "a"       "szent"   "borbála" "1."      "a"
  • Mivel a táblázatunk minden sora egy-egy oszlop volt, ezért a karaktervektor hosszúsága is a szavak számát adja meg. Ugyanakkor ha közvetlenül a fájlból importáltuk a szöveget, akkor a hosszúság a bekezdések számát jelenti (feltéve, hogy a 2.2.2.-ben leírtak szerint jártunk el.)

2.3.4. Szavak (betűk), írásjelek törlése

  • Ha csak a szavak érdekelnek, akkor az írásjeleket, melyek külön elemekként vannak eltárolva, törölnünk kell. Ha csak az írásjelek, akkor viszont a szavakat. Mivel a törlés úgy történik, hogy a törölt elemek üres helyként bent maradnak, ezért ezeket utóbb törölni kell. Az írásjelek törlésére két megoldást is mutatok, az egyik egy csomag (és függőségei) betöltését igényli. Az RStudio-ban egy többosztatú munkafelületünk van, az egyikben van egy Packages fül, arra kell kattintani, és ott kipipálni a kívánt csomagot. Eder és munkatársai stylo-ját is így kell betölteni – miután telepítettük. (A # kommentáromat jelöli, nem kell beírni. A \\W egy regex-kifejezés, amely minden nem-karaktert kijelöl. A != jelentése nem egyenlő – párja a ==, amely egyenlő-t jelent.)
# írásjelek törlése, be kell hívni a `tm` csomagot
szavak.v = removePunctuation(szoveg.v, preserve_intra_word_dashes = TRUE)

# alternatív módszer az eltávolításra, külön csomagot nem igényel
csakszavak.l = strsplit(szoveg.v, "\\W")
csakszavak.v = unlist(csakszavak.l)

# távolítsuk el az üres helyeket, azaz a törölt írásjelek helyét (ha a `tm` csomaggal töröltük az írásjeleket, akkor a `csakszavak.v` helyére értelemszerűen a `szavak.v` kerül)
not.blanks.v = which(csakszavak.v!="")
csakszavak.v = csakszavak.v[not.blanks.v]
  • Ellenőrizzük, milyen hosszú az írásjelek nélküli csakszoveg.v, illetve a szavak.v változónk! Az eredményből látni fogjuk, hogy nem teljesen azonos a hosszúságuk. Ennek az az oka, hogy az első módon történő eltávolítás során az olyan alakokat, amelyeket a lemmatizálás során a magyarlanc elemzője így ír föl, meg+van egy elemként őrzi meg (megvan), addig a másik módszer két külön elemre bontja és tárolja. (A \\w egy regex-kifejezés, amely csak a karaktereket jelöli ki [itt egy másik online tutorial hozzá].)
# szavak törlése
csakirasjelek.l = strsplit(szoveg.v, "\\w")
csakirasjelek.v = unlist(csakirasjelek.l)
not.blanks.v = which(csakirasjelek.v!="")
csakirasjelek.v = csakirasjelek.v[not.blanks.v]
  • Ennek az eljárásnak egy hibája van. Amennyiben a magyarlanc-cal feldolgozott anyagot használjuk, akkor megjelenik karakterként a +, amely azonban nem a regény írásjeleinek része. Ezeket is el kell távolítani. Az eddigi példák alapján ezt könnyű megcsinálni.

2.3.5. Változó fájlként történő elmentése

  • Amennyiben szükségünk van valamelyik változóra fájlként, kiírathatjuk. Jelen formájában minden szó/írásjel önálló bekezdésben lesz, ha ez zavar, akkor előtte egyetlen elembe másolhatjuk az összeset, és úgy is kiírathatjuk.
# másoljuk össze az elemeket
osszevont.csakirasjelek.v = paste(csakirasjelek.v, collapse = " ")

# írjuk ki fájlba
write(osszevont.csakirasjelek.v, file = "osszevont.csakirasjelek.txt", ncolumns = if(is.character(osszevont.csakirasjelek.v)) 1 else 5, append = FALSE, sep = " ")

Egy csomó mindent még tanulni kell. Majd máskor.

*: Nem pontos kifejezés, tudom.