import codecs
import re
print "Collecting..."
lineCounter = 0
kanjiCounter = 0
kanjiStatistics = []
inFile = codecs.open("data/jawiki-20090124-pages-articles.xml", "r", "utf-8")
outFile = file("data/wikipedia.kanji", "w")
chinesePattern1 = re.compile("\[\[zh:\W+\]\]")
chinesePattern2 = re.compile("\[\[zh-classical:\W+\]\]")
for line in inFile:
if re.search(chinesePattern1, line) != None: continue
if re.search(chinesePattern2, line) !== None: continue
kanjis = u""
for newKanji in line:
if ((ord(newKanji) >= 0x4e00 and ord(newKanji) <= 0x9fa5)
or (ord(newKanji) >= 0x3400 and ord(newKanji) <= 0x4db5)
or (ord(newKanji) >= 0xf900 and ord(newKanji) <= 0xfa2d)
or (ord(newKanji) >= 0x20000 and ord(newKanji) <= 0x2a6d6)
or (ord(newKanji) >= 0x2f800 and ord(newKanji) <= 0x2fa1d)):
kanjis = kanjis + newKanji
if len(kanjiStatistics) == 0:
kanjiStatistics.append({'kanji':newKanji, 'count':1})
print u"Znalazłem nowy znak:", newKanji, u"( znaków:", len(kanjiStatistics), ")"
else:
seenBefore = False
for oldKanji in kanjiStatistics:
if oldKanji['kanji'] == newKanji:
oldKanji['count'] = oldKanji['count'] + 1
seenBefore = True
break
if not seenBefore:
kanjiStatistics.append({'kanji':newKanji, 'count':1})
print u"Znalazłem nowy znak:", newKanji, u"( znaków:", len(kanjiStatistics), ")"
lineCounter = lineCounter + 1
kanjiCounter = kanjiCounter + len(kanjis)
if (lineCounter % 1000) == 0:
print "Linia", lineCounter, "ilość znaków:", kanjiCounter, "różnych znaków:", len(kanjiStatistics)
outFile.write(kanjis.encode("utf8"))
inFile.close()
outFile.close()
print u"Zapisuję wyniki..."
kanjiStatistics.sort()
outFile = file("data/statistics_wiki.txt", "w")
for kanji in kanjiStatistics:
print kanji['kanji'].encode("utf8"), ":", kanji['count'], "(", float(kanji['count'])/float(kanjiCounter*100), "percent )"
outFile.write(kanji['kanji'].encode("utf8") + " " + str(kanji['count']) + " " + str(float(kanji['count'])/float(kanjiCounter*100)) + "\n")
outFile.close()
print u"Zapisalem wyniki do data/statistics_wiki.txt"
Jest on niestety nieco dłuższy od poprzedniego i na pewno znajdzie się ktoś, kto powie mi, że jest on niezwykle nieefektywny pod względem prędkości działania. Rzeczywiście, przeanalizowanie pliku XML japońskiej wikipedii zajęło mojemu komputerowi ponad 25 godzin. Trudno. Program daje mi to, co chcę i to się liczy. A tym, co chcę jest oczywiście liczba wystąpień danego znaku we wspomnianym pliku XML. Aby uniknąć dołączania do statystyki znaków z języka chińskiego, program ignoruje wszystkie linki do stron wikipedii chińskiej (w wersji zarówno tradycyjnej, jak i uproszczonej). Nie jesteśmy w stanie oczywiście pominąć występujących na wikipedii nazw chińskich, ale przecież można argumentować, że one również są częścią języka.
Analiza częstotliwości występowania najczęstszych 1945 znaków, które powinny odpowiadać liście jouyou, chociaż nic tego nie gwarantuje (użycie znaków na pewno się z resztą zmieniło od czasu opracowania listy w 1981; z tego też powodu podpis osi poziomej na wykresie kłamie), przedstawiona została na rysunku poniżej.

Wniosek: po pokonaniu pierwszego, stromego zbocza eksponencjalnej krzywej nauki znaków kanji i opanowaniu pierwszego 1000 znaków (czyli dojścia do poziomu egzaminu JLPT na poziomie 2), powinniśmy być w stanie przeczytać zdecydowaną większość japońskiego tekstu i dalej powinno już być „z górki”.
Wykres otrzymałem ładując otrzymane dane do środowiska R za pomocą poniższego kodu.
png("odsetek.png", width=800, height=600, units="px")
dane <- read.table("statistics_wiki_seded.txt")
procentowe = sort(dane[,2]/sum(dane[,2]), decreasing=T)
plot(cumsum(procentowe[1:1945])*100, type="l", xlab="Numer znaku z listy jouyou", ylab="Odsetek znanych znaków na japońskiej wikipedii [%]", main="Znajomość znaków kanji")
jlpt = round((cumsum(procentowe)*100)[c(103, 284, 1023)])
abline(v=103, lty=3)
text(x=103, y=jlpt[1], paste("JLPT4 ", jlpt[1], "%", sep=""), pos=4)
abline(v=284, lty=3)
text(x=284, y=jlpt[2], paste("JLPT3 ", jlpt[2], "%", sep=""), pos=4)
abline(v=1023, lty=3)
text(x=1023, y=jlpt[3]-2, paste("JLPT2 ", jlpt[3], "%", sep=""), pos=4)
dev.off()
Brak komentarzy:
Prześlij komentarz