トップQs
タイムライン
チャット
視点

文字の出現頻度

ウィキペディアから

文字の出現頻度
Remove ads

文字の出現頻度(もじのしゅつげんひんど、: Letter frequency)とは、書記言語においてアルファベットひらがな漢字)などの文字が出現する回数の平均をまとめたものを指す。文字の頻度分析アラブ人数学者のアル=キンディー(801–873)が暗号解読を行うために確立したことから始まる[1]。またヨーロッパにおいては文字の頻度分析は1450年に活字が発明され、活字に必要な各字形の量を推定するために重要性を増した[2]。一方言語学者の間では未知の表記体系に対する言語同定英語版の技法として文字の頻度分析を行っている[3]

Thumb
英語における文字の出現頻度

文字の出現頻度や頻度分析暗号文ハングマンスクラブルWordleのような単語パズルゲームにおいて利用されており[4]、米国のテレビ番組『ホイール・オブ・フォーチュン』においても利用されている[5]エドガー・アラン・ポーの小説『黄金虫』では英文字の出現頻度の知見を活かして暗号文の解読を行った記述がある最も古い文献の一つであり、キャプテン・キッド秘蔵の財宝のありかを示すメッセージを頻度分析によって解読したことが書かれている[6]

ハーバート・ジム英語版は暗号学入門著書『Codes and Secret Writing』において英語の出現頻度は "ETAON RISHD LFCMU GYPWB VKJXZQ" の順序で出現頻度が高いとし、2文字(連接文字)に関しては "TH HE AN RE ER IN ON AT ND ST ES EN OF TE ED OR TI HI AS TO"、同じ文字が連続して出現する順序は "LL EE SS OO TT FF RR NN PP CC" である[7]。なお、出現頻度の加算方法の違いによって数値は多少変動する場合がある。

文字の出現頻度は一部のキーボード配列のデザインにも影響を与えている[8]ブリッケンデルファー型タイプライターDvorak配列Colemak配列英語版などは出現頻度の高い文字をホームポジションに配置している[9]

Remove ads

背景

要約
視点
Thumb
カリフォルニア・ジョブ・ケース英語版は19世紀に発明された印刷時において活字を収納するケースであり、文字の普遍性に応じて各文字のスペースが区切られている[10]

文書中における文字の出現頻度は暗号解読において研究され、特にアラブ人数学者のアル=キンディー(801–873)が頻度分析の手法を確立したことで広まったとされる(頻度分析を用いて解読できる暗号は頻度分析の前から存在するガイウス・ユリウス・カエサルが発明したシーザー暗号が挙げられ[11]、頻度分析自体はより以前から研究されていた可能性がある。)[1]。1450年にはヨーロッパにおいて活版印刷が発明され、活字ケースの区画スペースの大きさがそれぞれ違うことからも読み取れるように、活版印刷に必要な各文字の字形の量を推定する必要が生じたことで文字の出現頻度分析の重要性が増した[2]

すべての言語において厳密な文字の出現頻度の分布は文字の書き手によって使用する文法や単語が異なるため、求めることは不可能である[12]。しかしながら、ほとんどの言語において一定量の文書内での文字の出現頻度は特有の分布が現れる。例として、(互いに理解することが困難とされ、)極端な言語の変遷を経た古英語と現代英語それぞれの文字の出現頻度においても類似した特徴を持つことがある[13]。聖書のある一節における両者の文字の出現頻度は高い順に、古英語: enaid sorhm tgþlwu æcfy ðbpxz、現代英語: eotha sinrd luymw fgcbp kvjqxz となり[14]、違いとしては第一にそれぞれでのみ使用されている文字が存在することが挙げられるが、両者とも e が最も出現頻度の高い文字である[15]

英語圏でのライノタイプを使用していた職人の長年の経験と習慣から文字の出現頻度の高い順から低い順に etaoin shrdlu cmfwyp vbgkqj xz であると考えられており[16]、フランス語圏においては elaoin sdrétu cmfhyp vbgwqj xz の出現頻度であると考えられていた[17]

Thumb
モールス符号。Eを短点一つ、Aを長点一つ...と文字の出現頻度が高い順に短い符号が割り当てられている[18]

各アルファベットのモールス符号を通信にかかる時間が短いまとまり順に並べると e it san hurdm wgvlfbk opxcz jyq となる[注釈 1]。文字の出現頻度はMurray Codeのような他の電信システムにおいても考慮されている[20]

文字の出現頻度における同様の利用例としてはハフマン符号のような現代のデータ圧縮などが挙げられる[21]

文字の出現頻度は単語の出現頻度英語版と同様に書き手や記述されている内容によって異なった出現頻度となる[22]。フィクション小説を例としてみると、文章の時制が過去形で書かれることが多くなることから、d の出現頻度が高くなるとされている。またX線に関するエッセイの文字の出現頻度は x が異様に高くなることが考えられる[12]。加えて、執筆者の言葉の言い回しからも文字の出現頻度は影響を受けるとされる。例として、アーネスト・ヘミングウェイの文体とウィリアム・フォークナーの文体は明確に異なっている。単文字、bigram英語版trigram英語版、単語の出現頻度、単語の長さ、文章の長さを求めることで文章の表現方法が類似している著者の作品に対して、識別することが可能となる[23][12]

より厳密な文字の出現頻度は大規模な文書データを分析することで求めることができる。大規模な文書データに対する分析は現代のコンピュータと大規模なテキストコーパスを使用することで容易に行うことができる。より具体的には(出版記事、宗教文書、学術文書、フィクション小説など)さまざまな資料をもとに出現頻度を求めることができ[24]、フィクション小説においては hi の出現頻度の順は異なる位置となり、h の方がより普遍的に出現する文字とされている。

また同じ言語を使用する地域ごとにも文字の出現頻度はそれぞれ違いが存在している。例として、米国では "analyze"、"apologize"、"recognize" のように z が含まれた単語を用いているが、英国においてはこれらの単語がそれぞれ "analyse"、"apologise"、"recognise" のように異なった綴りで書かれている[25]。このことから米国における z の出現頻度は英国と比べて高くなっている。

アルファベットにおいて出現頻度の高い上位十二文字の割合は約 80% にも達する[26]。また上位八文字のみについても出現頻度は 65% に達する。文字の出現頻度はいくつかのランク関数によく適合し、中でも2つパラメータを持つベータランク関数が最も適合する[27]。パラメータを持たないランク関数も文字の出現頻度の分布に適合される(これらのランク関数はタンパク質構造におけるアミノ塩基の出現頻度を表す際にも使用されている[28][29]VIC暗号英語版ストラドリング・チェッカーボード英語版に基づいた暗号を使用するスパイは通常 "a sin to err"(2つ目の "r" を省略)[30][31] や "at one sir"[32] といった語呂合わせを用いて出現頻度の高い八文字を記憶する。

Remove ads

日本語における文字の出現頻度

要約
視点

平仮名

平仮名の出現頻度は以下の表の通りである[33][34]。分析に使用したデータにおける平仮名の総数は 20,711,361文字である[33]

さらに見る 順位, 平仮名 ...

片仮名

片仮名の出現頻度は以下の表の通りである[35][34]。分析に使用したデータにおける片仮名の総数は 3,608,288文字である[35]

さらに見る 順位, 片仮名 ...

漢字

文化庁によりまとめられた日本語における漢字の出現頻度上位50文字は以下の表の通りである[36]。分析に使用されたデータは総数177,276,398文字であり、そのうち漢字は51,258,216文字であった[37]。出現頻度の高い上位100文字はすべて常用漢字である[38]

さらに見る 順位, 漢字 ...

1993年の調査では、日本において使用される字体の異なる漢字の総数(異なり字)は計4476文字であり、出現頻度の高い漢字の上位500文字で出現頻度は約8割に達する[39]。また、出現頻度の高い漢字上位1600文字での出現頻度は約99%を占め、残りの約3000文字においては全体の1%程度の出現頻度となっている[39]

文字種別の出現頻度

日本語における記号、数字、平仮名、片仮名、漢字、アルファベットの文字の種類別の出現頻度は以下の通りとなる。

さらに見る 調査年, 文字種別出現頻度 ...
Remove ads

英語における文字の出現頻度

要約
視点
さらに見る 文字, 英語における相対出現頻度 ...

文字の相対出現頻度

Thumb
英話者が長期間使用したキーボード。E、O、T、H、A、S、I、N、R のキーには激しい摩耗が見られ、D、L、U、Y、M、W、F、G、C、B、P のキーにはある程度の摩耗が見られ、K、V、J、Q、X、Z のキーには摩耗がほとんど見られない。

文字の出現頻度を算出する方法は大きく三種類存在し、各方法によって文字の出現頻度の分布は大きく異なってくる。一つ目は辞書の見出し語として書かれている基本語英語版ごとに文字の出現頻度を加算する方法である[45]。以下の節ではこの方法により文字の出現頻度を求めている。二つ目は基本語の "abstract" を "abstracts"、"abstracted"、"abstracting" のように語形変化の単語ごとに文字の出現頻度を加算する方法である。この方法では、インターネット上で頻出する英単語のリストから文字の出現頻度を求める場合に、s のような文字の出現頻度がより現れるとされる。すなわち、s は複数形や三人称単数現在形の動詞中に付け加えられる文字であるため、非基本語の単語中に普遍的に現れる文字となっている。三つ目は実際の文書中に使用されている単語そのままを文字の出現頻度として加算する方法であり、これにより "the"、"then"、"both"、"this" のような単語の頻出により th の出現頻度がより現れるとされる。そして、絶対的な文字の出現頻度が求められるこの方法ではキーボードのレイアウトや古来の印刷機における文字の頻出度合いについて求めることができる。

英英辞典『Concise Oxford dictionary』を辞典内における単語の頻出度合を無視して文字の出現頻度を分析すると、順番は "EARIOTNSLCUDPMHGBFYWKVXZJQ" であった[45]

この出現頻度順はロベルト・ルワンド著『Cryptological Mathematics』を引用したパベル・ミツカ氏のウェブサイトにまとめられていたものである[46]

ルワンドによると、文字の出現頻度の高い順から並べると、etaoinshrdlcumwfgypbvkjxqz となることが言及されている。このルワンドの出現頻度順はコーネル大学の「Math Explorer's Project」による40000文字に対する文字の出現頻度順とは異なった並びとなっている[47]

英語における空白記号の出現頻度は英文字の出現頻度が最も高い e の約2倍となっており[48]、非アルファベット文字(数字、句読点など)総計の出現頻度は ta の間となる4番目(空白記号も含めた順位)に位置している[49]

単語の頭文字・末尾の文字の相対出現頻度

さらに見る 文字, 英単語の頭文字 ...

単語の頭文字の出現頻度を分析することは物理的空間におけるファイルや索引の量を割り当てるために重要視されている[51]。アルファベット 26 文字に対応したファイリングキャビネット英語版の引き出しを準備する場合に、各文字ごとに一つの引き出し、つまり 1:1 の割当を行うのではなく、頭文字の出現頻度に沿った引き出しの割当を行うことが合理的であると考えられる。すなわち、出現頻度の低い VWXYZ をまとめて一つの引き出しに割り当てる、出現頻度の高い s, a, c では Aa-An、Ao-Az、Ca-Cj、Ck-Cz、Sa-Si、Sj-Sz のように複数の引き出しを割り当てることが考えられる。同様の事例としては複数の巻に分かれた百科事典の構成や図書館において書籍の識別の名前の頭文字の分布を均等にするための Cutter number が挙げられる[52]

英単語全体および頭文字の出現頻度の分布は両者ともにジップ分布に従い、またユール分布英語版にも十分従うことが知られている[53]

一般的に数字の最初の桁の出現頻度の分布は数字全体の分布と比べて有意に差があるとされており、これはベンフォードの法則として知られている(ベンフォードの法則節を参照)[54]

ピーター・ノーヴィグ光学文字認識(OCR)を用いてGoogle Booksのデータにおける100,000単語以上出現する単語を対象にした英単語の頭文字の出現頻度が分析された[55]

Remove ads

ラテン文字を使用する言語における文字の相対出現頻度

要約
視点
さらに見る 文字, 英語 ...

*: İ および ドットなしI英語版 を参照。

下記の図はいくつかの国におけるラテン文字26文字の出現頻度を可視化したものである。各国はいずれも英語と同様に25文字程度のアルファベットを使用している[75]

さらに見る エスペラント語, スペイン語 ...

出現頻度のランキング

以下の表はいくつかの言語において出現頻度の高い10文字を並べたものである。

さらに見る 言語, 順序 ...
Remove ads

キリル文字を使用する言語における相対出現頻度

要約
視点

以下の表はキリル文字を使用する言語における文字の出現頻度を表している。

ロシア語Stefan Trost の分析結果をまとめたものである。分析には "WordCreator" の機能 Unicode Counter を使用した。分析にあたって利用したコーパスは 1,351,370文字(210,844単語)のもので、そのうち 1,086,255文字を集計している[78]。ただし、分析するコーパスによっては相対出現頻度は多少異なることがある。

ロシア語における出現頻度の高い文字(アルファベット)は OEA となる[78]

さらに見る 文字, ロシア語 ...
Remove ads

その他の言語における文字の相対出現頻度

要約
視点

ギリシア語

以下の表は Stefan Trost の分析結果をまとめたものである。分析には "WordCreator" の機能 Unicode Counter を使用した。分析にあたって利用したコーパスは 1,442,382文字(235,614単語)のもので、そのうち 1,161,745文字を集計している[89]。ただし、分析するコーパスによっては相対出現頻度は多少異なることがある。

左側の表はアルファベット順に並べたものであり、右側の表は出現頻度の高い文字順に並べたものである。ギリシア語における出現頻度の高い文字は AOE となる[89]

さらに見る 文字, ギリシア語における文字の出現頻度 ...

ヘブライ語

以下の表は Stefan Trost の分析結果をまとめたものである。分析には "WordCreator" の機能 Unicode Counter を使用した。分析にあたって利用したコーパスは 1,230,923文字(279,679単語)のもので、そのうち 937,426文字を集計している[90]。ただし、分析するコーパスによっては相対出現頻度は多少異なることがある。

左側の表は文字順に並べたものであり、右側の表は出現頻度の高い文字順に並べたものである。ヘブライ語における出現頻度の高い文字は יהו となる[90]

さらに見る 文字, ヘブライ語における文字の出現頻度 ...

ヒンディー語

以下の表は Stefan Trost の分析結果をまとめたものである。分析には "WordCreator" の機能 Unicode Counter を使用した。分析にあたって利用したコーパスは 978,430文字(238,604単語)のもので、そのうち 736,216文字を集計している[91]。ただし、分析するコーパスによっては相対出現頻度は多少異なることがある。

左側の表は文字順に並べたものであり、右側の表は出現頻度の高い文字順に並べたものである。ヒンディー語における出現頻度の高い文字は となる[91]

さらに見る 文字, ヒンディー語における文字の出現頻度 ...

中国語

中国語における文字の出現頻度の上位20文字は以下の表の通りである[92]。分析では2009年にインターネット上で人気のあった8つの小説から計12,379,116文字について調査したものである[93]

さらに見る 文字, 中国語における相対出現頻度 ...

中国の古文書における文字の出現頻度上位10文字は以下の表の通りである[92]。「不」、「一」、「人」の三文字は各年代において出現頻度が上位10位以内の高い頻度で表れる文字であった[92]

さらに見る 年代, 順序 ...

また、中国語の拼音(ピンイン)入力におけるアルファベットの出現頻度は以下の表の通りである[94]。分析には小説から約50万字、新聞記事から約130万字、ネットの投稿から約120万字を抽出したデータを使用している[95]ian の三つの文字の出現頻度が高く、v が最も出現頻度の低い文字であった[95]

さらに見る 文字, 中国語の拼音入力における相対出現頻度 ...

韓国語

韓国語ハングルにおける字母の出現頻度は以下の通りとなる[96]

さらに見る 順位, 字母 ...

韓国語のハングルにおける文字(音節)の出現頻度上位100文字は以下の通りである[97]

さらに見る 順位, 文字 ...

また、1950年代に調査された韓国の文書中におけるハングルの出現頻度の高い30文字は 이는다하 에가고올지어 의은서그아 로라기도한 나니를것있 리으여사들 の順である[98]。また、1950年代に調査された韓国語の文書中における漢字の出現頻度の高い30文字は 國生地人自 十一分物年 學大字發身 民氣方間會 日事對行上 當實等二法 である[99]

ベンガル語

ベンガル語で使用されるベンガル文字における文字の出現頻度は以下の表の通りである[100]

さらに見る 文字, ベンガル語における相対出現頻度 ...

またベンガル語の辞書の見出し語における文字の出現頻度は া ্র িন তকবপ ু মসলদ ে োঅগযচ জশ ীটহ য়ষধভণ ড়আ ঁখউ ৃফ ংূঙ ছইডথঘ ঞঠ ৈ ৌঝ ওএ ঃঢঢ় ঈঐঔঋঊৎ の順である[101]

タイ語

タイ語タイ文字における文字の出現頻度は以下の表の通りとなる[102]。分析に使用したデータにおける文字の総数は 354,221,260文字である[102]

さらに見る 順位, 文字 ...

タイ文字の子音における文字の出現頻度は高い順に รนกองมยวทดลตหสบคปจพขชธผศถณซษญภฐฟฉฒฝฎฏฤฮฑฃฬฆฌฅฦ である[102]。またタイ文字の母音、記号、数字における文字の出現頻度は高い順に า ่เ ้ ั ี ิะแไใ ุ ื ์ ู ็ ำโ ึๆฯ ๊๒๑๐๕๓๔๖ ๋๗๘ ํ ฺ฿ๅ๚๏๛ ๎ である[102]

アラビア語

アラビア語アラビア文字における文字の出現頻度は以下の表の通りとなる[103]。分析に使用したデータにおける語の総数は 1,297,259語、文字の総数は 5,122,132文字である[103]

さらに見る 文字, アラビア語における相対出現頻度 ...

台湾語

以下の表では台湾語における出現頻度の高い音節上位20文字を記載する[104][105]。なお、台湾語は文字の表記法として主に漢字(全漢)、漢字ローマ字混用(漢羅)、ローマ字(全羅)の三つ存在しているため、以下の表では漢字およびローマ字が混合した出現頻度となっている[106]

さらに見る 文字, 台湾語における相対出現頻度 ...

ビルマ語

ビルマ語で使用されるビルマ文字の基本字母における文字の出現頻度は以下の表の通りである[107]。ビルマ文字では 33 の文字が基本字母として存在している[107]

さらに見る 文字, ビルマ語における相対出現頻度 ...

また、ビルマ語の基本字母と併せて用いられる表音機能を持つ符号における出現頻度は以下の通りとなる[107]

さらに見る 文字, 相対出現頻度 ...

アムハラ語

アムハラ語で使用されるゲエズ文字(アムハラ文字)における文字の出現頻度は以下の表の通りである[108]。分析に使用したデータの文字の総数は 12,222,876文字である[108]

さらに見る 文字, アムハラ語における相対出現頻度 ...
Remove ads

関連の出現頻度

要約
視点

単語の出現頻度

ジップの法則

続いて文字の出現頻度ではなく、単語の出現頻度について言及する。ある自然言語のコーパスにおける単語の出現頻度はジップの法則に従った分布となる[109][110]。これは出現頻度の最も高い単語は二番目の単語の約二倍の出現頻度となることをいう[110]

エスペラント語で書かれたあるフィクション小説のコーパスにおける単語の出現頻度は以下の通りとなった:

la 9864、kaj 4195、mi 3934、de 2819、li 2543、esti 2395、al 1969... と続いている[111]

ジップの法則は集合の要素(文書内における単語など)を出現頻度の高い順に並べ、それぞれに順位を対応させると、各順位の出現確率 はその順位 の逆数におおよそ比例することを示している。ある順位における相対出現頻度は以下の式で与えられる[110]:

順位が高い 1、2、3、4、5 の順番に出現確率は 1、1/2、1/3、1/4、1/5 の比率を成している。したがってジップの法則から各順位ごとの出現確率はお互いに関連した関係であるといえる[110]。実際、上記の分析結果についても出現頻度はジップの法則に従っているといえる。

日本語

日本語における語(見出し語)の出現頻度は以下の表の通りである[112]

下記の表は割合を表示せず、順位のみを記載する。

さらに見る 順位, 単語 ...

英語

英単語の出現頻度は以下の表の通りである[113]。ただし、単語の出現回数の加算方法としては英語の辞書の見出し語(基本語)ごとに行っており、be には iswasarewere などが合算された数となるが、Ime は各々別の単語として加算されている。

下記の表は割合を表示せず、順位のみを記載する。

さらに見る 順位, 単語 ...

英語版の AWK には単語の頻度分析に関するプログラムがまとめられており、より高度な分析を行うプログラムについては下記のプログラム節に記載されている。

数字の出現頻度

Thumb
スーパーマーケットに並んでいる商品。日本においては価格の末尾の数字は 8 であることが多いとされる[114]

低価格帯

アルファベット平仮名に限らず、数字においても特徴的な出現頻度の事例が知られている。例として、日本のスーパーマーケットにおける商品の金額の末尾(一の位)の数字は 8 であることが多いことが知られている[115]。一方、アメリカやヨーロッパ、英語圏などのスーパーマーケットで見かける金額の末尾(一の位)の数字は 9 であることが多いことが知られている[116]。具体例として、商品の価格が200円でなく199円として売られていることが挙げられる。1997年の『Marketing Bulletin』によると、ニュージーランドの新聞の広告に記載された商品価格における末尾の桁の 60% が 9 であったことが知られている[117]

これらの事象を確認することは、大規模な統計的調査や統計学者による分析を行う必要なく容易に確かめることができる。

ベンフォードの法則

一方で潜在的な例として、企業の財務会計における数字の最初の桁に関する頻度について挙げることができる[118]。すなわち、最初の桁に現れる数字の出現頻度は互いに等しくなく、偏りがあることが知られており、これはベンフォードの法則と名づけられている。このベンフォードの法則によれば、数字の最初の桁において 1 である確率は 30% 程度であるが、9 である確率は 5% 未満である。このことから数字の最初の桁における分布をより正確に求めることで、不自然な偏りを検出し、不正や詐欺を発見するのに役立たせることができる[118]

数字の最初の桁における各数字の出現頻度を定量的に表すと、以下の表の通りとなる[119]。ただし、最初の桁の数値を とし、 の出現確率を とする。

さらに見る , ...

ベンフォードの法則では、対象となるデータセットが大規模なものでかつ一つ一つのデータが複数の桁を持ち、可能な限り実在するデータに対して現れる法則となる[120]

10進数の数字における最初の桁の出現確率は を底とする対数を用いて表される。すなわち、最初の桁の数値 の出現確率は以下の式で与えられる[54]:

これはすなわち、数字を横軸にとり、出現確率を縦軸とすると、各数字の出現確率は対数によって描かれる分布となる。したがって、数字の最初の桁における出現確率は特有の分布に従う[121]

大規模なデータセットに対する数字の二桁目の出現頻度についても同様に偏りのある分布となる[120]。しかしながら、数字の右側の桁の出現頻度を求めようとすると、次第にベンフォードの法則には従わなくなり、各数字の出現確率が均等(各数字約10%の出現確率)に近づいていくことが知られている[122]

なお、スーパーマーケットなどの低価格帯における末尾の数字は 8(9)であることが多いため、この性質は当てはまらない[123]

単語の長さ

各言語における単語の長さの平均値は Wordlengths - ウェイバックマシン(2007年10月2日アーカイブ分) にまとめられている。

このサイトの執筆者および分析を行ったコーパスの詳細についてはほとんど不明で、Unicode のテストを行うための文書について分析を行ったことのみが判明している[注釈 3]

単語の長さを算出する方法は主に三種類存在する[124]。一つ目は語の形態に応じて語の長さを算出する方法である。これはある単語に対してその本体の自立部分と、助詞、助動詞などの付属部分を別々のものとみなして計算する方法である[125]。二つ目は語の表記に応じた語の長さを算出する方法である。これはある単語に対して文字として表記されているそのままの文字数を一つの単語として計算する方法である[126]。三つ目は語の音に応じた語の長さを算出する方法である。これはある単語に対してそれぞれの文字を拍(モーラ)に応じて語の長さを計算する方法である[126]

1986年に出版された『中央公論』1年分のデータを標本とした日本語における単語の長さの平均は、形態別の算出方法では 1.8723 となり、表記別の算出方法では 3.6704 であり、音別の算出方法では 4.7798 であった[125]

Remove ads

実装

要約
視点

AWKによる頻度分析プログラム

説明

以下に記載されているコードはエスペラント語における頻度分析を行うプログラムで AWK によって書かれている。出力形式として ASCIIHTMLWikitable およびヒストグラムを対応している[注釈 4]。頻度分析が可能な項目として以下のものが挙げられる:

  • (単なる)文字の出現頻度
  • 単語の頭文字の出現頻度
  • 単語の末尾の文字の出現頻度
  • 単語の長さの平均値とその分布
  • 単語の出現頻度

BEGINパターンでは分析する頻度の機能を自由に有効・無効化することができ、出力形式のフォーマットを指定することもできる。通常下記のプログラムの頻度分析は大規模なテキストコーパスの分析についても数十秒の実行時間で終了することが多い。しかし、計算機の処理速度やテキストコーパスの規模によっては単語の出現頻度を求めるのに数十分かかる場合がある。したがって、始めて分析するコーパスの実行においては単語の出現頻度分析を無効にして実行すること推奨する。

単語の出現頻度算出機能の一つとして単語を品詞ごとに分けて名詞(-O)、形容詞(-A)、副詞(-E)、(分詞を含まない)動詞、およびその他の品詞ごとに分類することができる。

言い換えれば、複数形と対格形については基本的に -O、-A、-E の形として導かれる。すなわち、"vin" や "tiujn" のような単語はそれぞれ "vi" や "tiu" となる。また動詞の語尾 "-as"、"-is"、"-os"、"-us"、"-u" は "-i" として導かれる。動詞の分詞についても -O、-A、-E の単語になり、例えば "amantojn" は "amanto" となり "ami" にはならない。

BEGINパターンに含まれている例外の単語処理(正規表現の部分)に注意を払う必要がある。これらの処理によって頻度分析において "nun" を "nu" の対格形としてではなく、"kaj" は "ka" の複数形ではなく、"unu" が "uni" の命令形ではないことを正しく判別する。もっともすべての単語を正しく処理できるわけではない。例として、エスペラント由来でない名前の "Simon" では "simo" と誤って変形されてしまう。これを回避するために必要に応じて該当のリストを拡張することが可能である。

プログラムの使用方法として、下記の折り畳みボックス内のコードをコピーし、テキストファイルに貼り付け保存(frequency.awk)。これをターミナルにて以下のコマンドを実行する:

awk -f frequency.awk text.cx >result.cx

もしくは各環境に対応したコマンドを実行する。なお、このプログラムを実行するためには実行環境内に AWK をインストールしておく必要がある。Linux、Unix 環境ではデフォルトでは AWK が搭載されており、Mac も同様に動作すると考えられる。Windows については Gnu-a website からプログラムファイルをダウンロードすることでプログラムを実行することができる。

このプログラムを実行することによって任意のコーパスに対して単語の頭文字および末尾の文字の出現頻度、単文字の出現頻度、単語の長さの平均値と分布、あるいは単語の出現頻度の頻度分析が可能となる。

プログラム

AWK
BEGIN {
# 以下のコードは適宜修正してください

# 分析に関する設定項目 - 1: 有効化、0: 無効化

LETTER_FREQUENCY  = 1
FIRST_LETTERS_OF_WORD = 1
LAST_LETTERS_OF_WORD = 1
WORD_LENGTH  = 1
WORD_FREQUENCY  = 1 # 実行に時間がかかる

# 出力形式に関する設定項目 - 1: 有効化、0: 無効化

FORMAT_ASCII = 1
FORMAT_HTML = 1
FORMAT_WIKI = 1

# 例外の単語

NO_VERB = "^(tiu|kiu|neniu|unu|c[x]u|c[x]iu)$"
NO_ALL_WORD = "^(kaj|tuj|nun|kun|sen|ajn|plej|malplej|tamen|amen|kvin)$"
NO_ROMAN = "^(mil|((c|ci|cim|ĉ|div|divid|il|l|lic|lim|m|v|vic|vid|viv)i))$"

# lili、livi、vili もローマ数字の例外のとして挙げられるが、ほとんど場合で考慮する必要はない

start_time=systime(); # systime() 関数が使用できない環境下では除去する必要がある。

# ==================================================================================
version="Version: 2012-01-18 17:00 Pejno Simono";

FS="[ \n\t\",.;:!?()]"; # 考慮する
}

{
gsub(/[-]/,"");
for(i=1; i<=NF; i++)
if($i~/^[a-zA-Z][a-zA-Z]+$/) # 少なくとも2文字以上
{
s=tolower($i);
if(s!~/^[ivxlcdm]+$/ || s~NO_ROMAN) # ローマ数字以外
{
n=0;
for(j=1; j<=length(s); ) # 任意の文字
{
c=substr(s,j,1);
if (c~/^[cghjsu]/)
if (substr(s,j+1,1)=="x" && substr(s,j+2,1)!="x")
c=substr(s,j,2);
if(j==1)
first[c]++; # 単語の頭文字
letter[c]++;
letters++;
j+=length(c); # 単語中の "x" まで飛ばす(X-方式)
n++;
}
last[c]++; # 単語の末尾の文字

if(n>1) # 単語の長さが 1 より大きい場合のみ
{
length[n]++; # 単語の長さ
sum+=n;
words++;

if(WORD_FREQUENCY==1)
{
s=tolower($i); # すべての単語に対して
j=length(s);
if(j>2)
{
if(s!~NO_VERB)
n=sub(/(as|is|os|us|u)$/,"i",s);
if(n==0 && s!~NO_ALL_WORD)
sub(/(jn|j|n)$/,"",s);
}
word[s]++;
}

}
}
}
}

END {
FIRST=1;
LAST=2;
ALL=3;
LENGTH=4;
WORDS=5;

ASCII=1;
HTML=2;
WIKI=3

asciiwidth=50;
htmlwidth=400; # pixel
wikiwidth=400; # pixel

if(LETTER_FREQUENCY>0)
{
if (FORMAT_ASCII>0) printout(ALL,ASCII);
if (FORMAT_HTML>0) printout(ALL,HTML);
if (FORMAT_WIKI>0) printout(ALL,WIKI);
}
if(FIRST_LETTERS_OF_WORD>0)
{
if (FORMAT_ASCII>0) printout(FIRST,ASCII);
if (FORMAT_HTML>0) printout(FIRST,HTML);
if (FORMAT_WIKI>0) printout(FIRST,WIKI);
}
if(LAST_LETTERS_OF_WORD>0)
{
if (FORMAT_ASCII>0) printout(LAST,ASCII);
if (FORMAT_HTML>0) printout(LAST,HTML);
if (FORMAT_WIKI>0) printout(LAST,WIKI);
}
if(WORD_LENGTH>0)
{
if (FORMAT_ASCII>0) printout(LENGTH,ASCII);
if (FORMAT_HTML>0) printout(LENGTH,HTML);
if (FORMAT_WIKI>0) printout(LENGTH,WIKI);
}
if(WORD_FREQUENCY>0)
{
if(FORMAT_ASCII>0) printout(WORDS,ASCII);
if(FORMAT_HTML>0) printout(WORDS,HTML);
if(FORMAT_WIKI>0) printout(WORDS,WIKI);
}

if(start_time>0) print time_needed();
print version;
}

function printout(mode,format)
{
if(mode==FIRST)
return printout2(mode,format,first);
if(mode==LAST)
return printout2(mode,format,last);
if(mode==ALL)
return printout2(mode,format,letter);
if(mode==LENGTH)
return printout2(mode,format,length);
if(mode==WORDS)
return printout2(mode,format,word);
}

function printout2(mode,format,A)
{
setup(mode);
if(format==ASCII)
return printoutASCII(mode,A);
if(format==HTML)
return printoutHTML(mode,A);
if(format=WIKI)
return printoutWIKI(mode,A);
}

function setup(mode)
{
_col=2;
_asc=0;
_colhdr="letter";
_colalign="center";
_counted="words";
_count=words;
_mez=", average word length";
_mez2="letters";

if(words>0)
_av=sum/words; # 単語の長さの平均値
if(mode==FIRST)
{
_title="First letters of a word";
return;
}
if(mode==LAST)
{
_title="Last letters of a word";
return;
}
if(mode==ALL)
{
_title="All letter";
_counted="letters";
_count=letters;
return;
}
if(mode==LENGTH)
{
_title="Word length";
_col=1;
_asc=1;
_colhdr="length";
return;
}
if(mode==WORDS)
{
_title="Word frequencies";
_colhdr="word";
_colalign="left";
}
}

function printoutASCII(mode,A, i,j,B,w,s,fmt)
{
if(_count<1)
{
print "file empty";
return;
}
i=sillysort(A,B,_col,_asc);
if(mode!=LENGTH) # 最高値
j=B[1,2]
else
j=getmax(B);
w=asciiwidth/j;
print "<" "pre>";
printf("=== %s ===\n\n",_title);
if(mode==WORDS)
fmt="%-20s\t%8s %s\n";
else
fmt="%-6s\t%8s %s\n";
printf(fmt,_colhdr,"number","probability\n")
if(mode==WORDS)
fmt="%-20s\t%s %6.2f%% %s\n";
else
fmt="%-6s\t%s %6.2f%% %s\n";
for(j=1; j<=i; j++)
{
s=B[j,1];
if(mode!=WORDS)
s=toupper(s);
printf(fmt, s, thou(B[j,2],8), 100.0*B[j,2]/_count, hist(B[j,2]*w));
}
printf("\nEl %s %s", thou(_count,0), _counted);
if(mode==LENGTH)
printf("%s %0.2f %s", _mez, _av, _mez2);
printf "\n</" "pre>\n\n";
}

function hist(w, s)
{
w-=0.5;
while(w-- > 0)
s=s "*";
return s;
}

function printoutHTML(mode,A, i,j,B,w,s)
{
if(_count<1)
{
print "file empty";
return;
}
i=sillysort(A,B,_col,_asc);
if(mode!=LENGTH) # 最高値
j=B[1,2]
else
j=getmax(B);
w=htmlwidth/j;
printf("<table border=1>\n");
printf("<tr><th colspan=4>%s</th></tr>\n",_title);
printf("<tr><td align=%s>%s</td><td align=right>number</td>", _colalign, _colhdr);
printf("<td align=center colspan=2>probability</td>\n");
for(j=1; j<=i; j++)
{
s=B[j,1];
if(mode!=WORDS)
s=toupper(s);
printf("<tr><td align=%s><b>%s</b></td>", _colalign, s);
printf("<td align=right>%s</td>", thou(B[j,2]),0);
printf("<td align=right>%0.2f%%</td>", 100.0*B[j,2]/_count);
printf("<td align=left><div style=\"width:%dpx;",B[j,2]*w);
printf("height:2ex;background:blue;\">&#160;</div></td>\n");
}
printf("<tr><th colspan=4>El %s %s", thou(_count,0), _counted);
if(mode==LENGTH)
printf("%s %0.2f %s", _mez, _av, _mez2);
printf("</th></tr>\n");
printf("</table>\n\n");
}

function printoutWIKI(mode,A, i,j,B,w,s)
{
if(_count<1)
{
print "file empty";
return;
}
i=sillysort(A,B,_col,_asc);
if(mode!=LENGTH) # 最高値
j=B[1,2]
else
j=getmax(B);
w=100.0*j/_count;
w=wikiwidth/w;
printf("{| class=\"wikitable\"\n");
printf("! align=center colspan=4 | %s\n",_title);
printf("|-\n! align=%s | %s !! align=right | number !! align=right colspan=2 | probability\n",_colalign,_colhdr);
for(j=1; j<=i; j++)
{
s=B[j,1];
if(mode!=WORDS)
s=toupper(s);
printf("|-\n| align=%s | <b>%s</b> ",_colalign,s);
printf("|| align=right | %s ", thou(B[j,2],0));
printf("|| align=right | {{bartable|%0.2f|%%|%0.3f}}\n", 100.0*B[j,2]/_count, w);
}
printf("|-\n! colspan=4 | El %s %s", thou(_count,0), _counted);
if(mode==LENGTH)
printf("%s %0.2f %s", _mez, _av, _mez2);
printf("\n");
printf("|}\n\n");
}

function getmax(A, i,j,M)
{
for(i in A)
{
split(i, M, SUBSEP);
if(M[2]==2)
if(A[i]>j)
j=A[i];
}
return j;
}

function sillysort(A,B,col,asc, i,j,n,t)
{
for(j in A)
{
i++;
B[i,1]=j;
B[i,2]=A[j];
n=i;
if (asc==0) # desc
{
while(n>1 && B[n,col]+0>B[n-1,col]+0)
{
t=B[n-1,1]; B[n-1,1]=B[n,1]; B[n,1]=t;
t=B[n-1,2]; B[n-1,2]=B[n,2]; B[n,2]=t;
n--;
}
}
else # asc
{
while(n>1 && B[n,col]+0<B[n-1,col]+0)
{
t=B[n-1,1]; B[n-1,1]=B[n,1]; B[n,1]=t;
t=B[n-1,2]; B[n-1,2]=B[n,2]; B[n,2]=t;
n--;
}
}
}
return i;
}

function time_needed( h,m,s,eps)
{
eps=0.000001;
s=systime()-start_time;
m=int(s/60);
s-=m*60-eps;
h=int(m/60);
m-=h*60-eps;
return sprintf("Run time (hms): %i:%02i:%02i\n",h,m,s);
}

function thou(v,n, s)
{
s=sprintf("%d_",v);
while(s~/[0-9][0-9][0-9][0-9]/) # エレガント
sub(/[0-9][0-9][0-9][,_]/, ",&",s); # 興味深い
sub(/_/,"",s); # エレガントでない
while(length(s)<n)
s=" " s;
return s;
}

function _thou(v,n, i,j,s,t)
{
s=sprintf("%d",v);
for(i=length(s); i>0; i--)
{
t=substr(s,i,1) t;
if(++j%3==0)
t="," t;
}
while(length(t)<n)
t=" " t;
return t;
}
Remove ads

脚注

参考文献

関連項目

外部リンク

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads