Perlを使った単語頻度プログラム

このQ&Aのポイント
  • Perlを使った単語頻度プログラムの作成方法について教えてください。
  • ファイル1には英文が記載されており、ファイル2には単語とその出現回数が記載されています。
  • ファイル2の単語とファイル3での出現回数を照合し、出現回数の多い順に文をソートするプログラムを作成したいです。
回答を見る
  • ベストアンサー

Perlを使った単語頻度プログラム

ファイル1には 英文 I will go by car to the airport. I bought prior to boarding a plane to and snacks. //改行 Upon arrival at Los Angeles International Airport, was not able to go to the local tourist hit by heavy rain. ... のように英文が数十行記載されています。 ファイル2には Car car level1 Airplane airplane level1   Snacks  snacks level2 ... EOS Upon upon level3 ... というように、第一引数に単語、第二引数に小文字の単語、最後にレベル(あまり意味をなさない・・・)が記載されているとします。EOSは改行です。 ファイル3には car : 3 airplane : 1 snacks : 1 というように予めファイル1の中での各単語の出現回数をカウントしたテキストとなります。 この三つのファイルをもとに、 まずファイル2を読み込んでファイル2内の第二引数とファイル3の単語で同じものがあれば、カウント変数に出現回数(ファイル3内の数値)を加算することを繰り返し、それをEOSの行になるまで繰り返し、ファイル1での該当の行と、EOSまでの出現回数を出力し、その都度、出現回数の多い順に文をソートするプログラムを教えてください。 結果例 1 :  123  : I will go by car to the airport. I bought prior to boarding a plane to and snacks. 順位:出現回数:文

  • Perl
  • 回答数1
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

こんにちは。 1つ質問させてください。 Perlでプログラム言語をかけますか? 区切り文字などの指定がなかったので ご自分で編集することができるということであれば ざっくりとプログラムを回答させてもらいます。 EOSは改行とありますが、level表記の後には改行はないのでしょうか? Car car level1 Airplane airplane level1 Snacks  snacks level2 ... [改行] Upon upon level3 ということでしょうか? あと、要望の確認ですが、 1.三つのファイルがあります。 2.ファイル2を読み込んでファイル2内の第二引数を配列Aに取り出します。 3.ファイル3を読み込んで単語と、出現回数のハッシュBに取り出します。 4.配列Aの単語がハッシュBのキーと一致する(単語で同じものがあれば)場合   ハッシュBの値を加算してハッシュB2をつくります。 5.ファイル1を配列Cに読み込みます。 --------------------------------------- ここまではなんとなくわかるのですが、それ以降がよくわかりませんので わかりやすく説明していただけると助かります。 (該当行というのが不明なのですが)ハッシュBのキー(もしかしたら配列A)の単語が  含まれている配列Cを探し出す。(複数行含まれている場合は1つだけ?) 該当の行(配列Cの行番号のこと?)と、EOSまでの出現回数(これはをハッシュB?それともハッシュB2??)を出力し、その都度、出現回数の多い順に文をソートするプログラム

wiredrikou
質問者

補足

質問文が不明瞭ですみませんでした。 >EOSは改行とありますが、level表記の後には改行はないのでしょうか? level の後には改行となっています。 Car car level1 ¥n Airplane airplane level1 ¥n  Snacks  snacks level2 ¥n ... EOS ¥n Upon upon level3 ¥n > 該当行というのが不明なのですが)ハッシュBのキー(もしかしたら配列A)の単語が  含まれている配列Cを探し出す。(複数行含まれている場合は1つだけ?) 複数行にわたって含まれている場合は1つだけでお願いします。 > 該当の行(配列Cの行番号のこと?)と、EOSまでの出現回数(これはをハッシュB?それともハッシュB2??)を出力し、その都度、出現回数の多い順に文をソートするプログラム 出現回数はハッシュB2でお願いします。

関連するQ&A

  • 単語の出現頻度を求めるプログラム

    book.eng(英文がいっぱい)に現れている, 単語の出現頻度を求めるプログラムを作りたいのですが、大まかにまとめると次のような作業をしたいのです。 1.ファイルから一行読み出す 2.読み出した行を単語に分解 3.単語をキーとして、連想配列を用いたカウンターの増加 4.全部読み終わったら、キーを用いて出力 while( $input = <> ) { #読み出した一行を単語に分解(splitを使った方がいいのかな) #単語の数だけ繰り返し #単語をキーとして連想配列に } #全部終わったので、出力 という感じになりそうなのですが。。。。 ちなみにAND, And, andはすべて同じ単語だから、一行をすべて小文字に変換しておいた方がよさそうですよね。 $input =~ tr/[A-Z]/[a-z]/; を使えばいいとおもうのですがイマイチよく分かりません。そして出力もきれいにしたいし、一般性を持たせるなら、単語を切り分ける正規表現を引数として渡せるようにしておきたいです。どなたか教えてくださいませんか。

    • ベストアンサー
    • Perl
  • awkとsedを使ってある単語が何回出てきているのかという頻度を調べたいのですが、誰か助けて下さい!!!

    まず、単語とその単語の得点が書かれてあるファイルがあります。 ●ファイル例(番号、単語名、得点) 1_フリップフロップ______________3510.00 2_入力________________________2.00032 3_回路__________________________23.666 4_出力__________________________230.00 5_状態__________________________325.04 6_順序回路____________________220.90 7_入力端子____________________71.020 8_論理_____________________1.0000003 9_マスタフリップフロップ_________143.70 10_パルス幅_____________________35.55 11_TCP/IP___________________6666.6 ・ ・ ・ ある文章中に、このファイルの単語が出現する回数と、各々の単語の得点の合計、 すべての単語の得点の総得点を出力させたいのです。 出力としては次のような形が理想です。 ●出力ファイル例(はじめに総得点、その下に番号、単語名、得点、出現回数、合計) 文章の総得点_=_35553836.07327262 1_フリップフロップ______________3510.00_____________23___________80730.00 2_入力________________________2.00032_____________19___________38.00608 3_回路__________________________23.666_____________14____________331.324 4_出力__________________________230.00_____________17____________3910.00 5_状態__________________________325.04_______________4____________1300.16 6_順序回路____________________220.90_______________8____________1767.20 7_入力端子____________________71.020______________15____________1065.30 8_論理_____________________1.0000003_______________6_________6.0000018 9_マスタフリップフロップ_________143.70_______________7_____________1005.90 10_パルス幅_____________________35.55______________15______________533.25 11_TCP/IP___________________6666.6________________9_____________59999.4 ・ ・ ・ なお、得点の桁はできるだけどのような桁も表示できるようにしたいと考えています。 またファイル中の「_」は空白を意味しています。 どなたかどうかよろしくお願いします!!!!!!!!

  • ファイルから文字列(英単語)を比較して数える

    現在perlを勉強中の身です。 1行に1英単語があり、それが100~200行に渡ってあるファイルがあります。 このファイルの単語に重複しているものはありません。Xとします。 また別のファイルにも同様に1行に1英単語があり、それが100~200行に渡ってあるファイルがあります。 このファイルの単語は重複しているものがあります。Yとします。 当然、最初のファイルにある単語もない単語もあります。 ファイルXから単語を読み取りYでその単語が何回出現したかチェックして単語と出現回数を出力するようなプログラムを組みたいと考えています。 参考書やインターネットで調べたところ、単語を数えるプログラム等はあるのですが、ファイルを読み込みさらにファイルを読み込んで比較する、といった流れのプログラムを見つけることができませんでした。 遠回りな考え方だと 例えば ファイルX a b c d(本当は単語間は改行があり1行1単語なのですが、見やすさのためにこのように表記しました。) ファイルY c c d e f とあった場合まず二つのファイルを結合し ファイルZ a b c d c c d e f として二回以上出現した単語のみを抜き出し ファイルZ' c 2 d 1 (この時出現回数を-1回する) としてファイルXと結合して出現回数を足して-1すると ファイルX' a 0 b 0 c 2 d 1 のようにできるのではないかと考えてはいます。しかし遠回り過ぎてスマートではないように感じます。 どのような考え方、そしてどのようなプログラムを組めばよいのでしょうか。ご教授お願い致します。

    • ベストアンサー
    • Perl
  • Perlのアルゴリズムについて教えてください!

    データファイルAとデータファイルBからデータを受け取って、データファイルB中の第i番目の文Siの重要度を式1に基づいて計算して、重要度と順位(重要度の高い順に1位、2位、、)を各文Siに付与するアルゴリズムを考える場合、式1のWi,jは文Siに出現するj番目の単語で、niはSiに出現する単語の数となる。Wi,jの出現頻度はファイルAから得られるものとする。 /*データファイルA*/ はじめ:␣12 改行 こる:␣1 改行 いく:␣23 改行 みせ:␣4 改行 ... というように前に文字列(基本形)が入り後ろに数字が記載されているデータ /*データファイルB*/ はじめ␣はじめ␣形容詞 改行 こる␣こる␣形容詞 改行 ... EOS 改行 ... ␣は空文字 1.ファイルAにまだ読み込んでいない行がある限り繰り返す    1-1.ファイルから一行読み込む    1-2.その行の基本形用のカウンタを用意して、そのカウンタにその基本形の出現頻度を代入する。 2.文番号カウンタと文重要度変数を用意して、初期値をそれぞれ1と0にする。 3.データファイルBにまだ読み込んでいない行がある限り繰り返す 3-1.ファイルから1行読み込む 3-2.もしその行がEOSであれば、文番号カウンタと文重要度変数の値を出力する。その後、文重要度変数を0にして、文番号カウンタを1増やす。 3-3.これ以降のアルゴリズムが解けないので教えてください。

  • ハッシュ(単語数を数える) たのしいRuby

    たのしいRuby P252に掲載されていた、例題 「ハッシュ(単語数を数える)」の解説を読んでも 意味が分からなかったので教えてください。 ■例題word_count.rb 1:# 単語数のカウント 2: 3: count = Hash.new(0) 4: 5:## 単語の集計 6:while line = gets 7: words = line.split 8: words.each{|word| 9: count[word] += 1 10: } 11:end 12: 13:## 結果の出力 14:count.sort{|a,b| 15: a[1] <=> b[1] 16:}.each{|key, value| 17: print "#{key}: #{value}\n" 18} ■疑問1. 解説には、 # 3行目で出現回数を記録するハッシュcountを作ります。 # countは、キーが単語、値がその単語が出現した回数を表します。 と書かれているのですが、「キーが単語、値がその単語が出現した回数を表します」 の内容が理解できません。newしただけなのに、どうして、 キーと値の内容が決まるのでしょうか? ■疑問2. 解説には、 # 8行目からの繰り返しでは、それぞれの単語をキーにして、countから出現回数を取り出し、 # +1します。 と書かれているのですが、「count[word] += 1」 の内容が理解できません。 作成したハッシュcountと、getsメソッドで読み込み単語単位に分割した配列wordsとが、 どこで関連付けされているのかが、分かりません。 ■疑問3. 解説には、 # ruby word_count.rb README という形で、Rubyに同梱されているREADMEファイルの単語数を調べた 実行結果が掲載されているのですが、 そのときの具体的な処理の流れが分かりません。 「ruby word_count.rb README」と書くだけで、 処理の流れが、getsの所まできたとき、 自動的に指定ファイル名を判断し、 読み込みを始めるということなのでしょうか。

    • ベストアンサー
    • Ruby
  •  キーワード出現頻度解析 がわかりません

     ○キーワード出現頻度解析というところがあり http://www.searchengineoptimization.jp/tools/keyword_density...   [ 例えば、「朝の天気予報」という文の場合、単語に分けると「朝/の/天気/予報」という4つの単語に切り分けられます。この文での「朝」という単語のキーワード出現率は、1/4X100=25(%)となります。] ということらしいのですが 作ったサイトをこの解析にかけましたら 下記のような結果になりました ~~~~~~~~~~~~~~~ File index.html [text/html] タイトル要素 恋ノウタ(恋愛専門待受サイト) meta keywords 恋愛待受,恋する女,恋空,恋占い,恋の詩,ひだまり, meta description 構成単語数 63 総単語数 88 出現頻度 ※頻出回数10回未満の単語を省略 ~~~~~~~~~~~~ 本当なら ○○のキーワードが何%とでてくるはずなんです この結果の意味がわからないことと 恋のキーワードで10%にしたいのですが どこをどう直したらよいのか全くわかりません どなたか教えていただけますか?

  • 単語の出現回数を数え、出現回数順に表示するには?

    標準入力または入力ファイルから単語の出現回数を調べるプログラムの一部です。ENTRY *add_entry(ENTRY *new)関数で以前に出てきた単語か(正確には以前に同一内容の行があったかを)判断し、既出ならばvoid do_one(FILE *fp)関数内部でp->count++として出現回数に加算しています。void do_one(FILE *fp)関数の最後の方のprintfで単語とその出現回数を表示します。これだとappleという単語が2回出てくれば、 apple:1 apple:2 と表示されます。この場合は apple:2 だけ表示させ、さらに、出現回数の多い順に単語を並べて表示させたいんです。どういう風にすればいいでしょうか? typedef struct entry_t { char *str; struct entry_t *next; int count; /* 単語の出現回数 */ } ENTRY; int main(int argc, char **argv) { FILE *fp; char *s; init_hash(); --argc; ++argv; if (argc == 0) do_one(stdin); else { while (argc--) { if ((fp = fopen(*argv, "r")) == NULL) cant(*argv); /* no return */ do_one(fp); fclose(fp); argv++; } } free_all_entries(); return (0); } void do_one(FILE *fp) { ENTRY *p; char buf[MAX_SIZE]; int i; while (fgets(buf, MAX_SIZE, fp) != NULL) { if ((p = malloc(sizeof(ENTRY))) == NULL) error("can't alloc memory"); /* no return */ if ((p->str = strdup(buf)) == NULL) error("can't alloc memory"); /* no return */ if (add_entry(p) != p) { p->count++; /* 登録済みなので単語の出現回数を1増やす */ free(p->str); /* すでに登録されているので開放 */ free(p); } else /* 新しく単語を登録する場合 */ p->count =1; /* 単語の出現回数を1にする */ printf("%s : %d\n", p->str, p->count); } } void init_hash(void) { int i; for (i = 0; i < HASHSIZE; i++) table[i] = NULL; } ENTRY *add_entry(ENTRY *new) { ENTRY *p; int h; h = hash(new->str); /* 追加する単語のハッシュ値を求める */ for (p = table[h]; p != NULL; p = p->next) if (strcmp(p->str, new->str) == 0) { /* 追加済みの単語ならば */ return (p); /* そのデータのポインタを返す */ } new->next = table[h]; table[h] = new; /* 単語を追加する */ return (new); }

  • 英単語(英文字で最大15文字)を*があわられるまで1つずつ読み込み、読

    英単語(英文字で最大15文字)を*があわられるまで1つずつ読み込み、読み込んだ英単語の文字数を計算して同一文字数の単語の出現回数を表示するプログラムです。 以下のプログラムを関数の引数及びその中実行文中でポインタ変数を使用するものを作りたいのですが、以下のプログラムは正常に動いているのですが、関数が使われていません。どう分けていいか分からないので教えてくださると助かります。 #include<stdio.h> int main(void) { char mojiretu[15],*pmoji int con[15]={0},i,j; pmoji=&mojiretu[0]; printf("課題データ\n"); scanf("%s",mojiretu); while(*pmoji!='*') { for(j=0;*(pmoji+j)!='\0'j++) {} con[j-1]++; scanf("%s",mojiretu); } printf("文字数\t出現回数\n") for(i=0;i<=14;i++) printf("%d\t%d\n",i+1,con[i]); }

  • 形態素解析とtfidf計算処理のjavaプログラム

    二つのプログラムを作成しようと思っています。 1、一行に「単語<tab>数字列(132:1,83:2,........)」という形のデータが存在するファイルを読み込んで、単語の部分(殆ど名詞)だけ抽出し形態素解析(cmecabを使用)して名詞の何の種類かによって値を与え、一行に「単語<tab>値」という形でテキストファイルに出力するプログラム 値について 一般名詞、固有名詞の場合:2 形容動詞語幹の場合:1 サ変接続、副詞可能、ナイ形容詞語幹、接尾、非自立の場合:0.5 代名詞、数詞、その他(動詞や副詞、接頭詞)の場合:0 例:読み込むファイルの中身(単語<tab>文書番号:その文書での単語の出現回数,.........) 小学校 76:1,167:1,254:1,395:1,400:1,488:1 旦那 183:1 委員 275:1 最終 401:1 月曜日 376:1 以下のプログラムはCmecabでテキストファイルを読み込んで形態素解析し出力するプログラム。これを改造すればいけると思っています。 // 引数に解析したいファイルを指定 // 結果は"cmecab-output.txt"に出力 // コンパイル方法"javac -encoding utf8 cmecab.java" // 入力ファイルの文字コードはUTF8で保存しておく // 出力ファイルの文字コードもUTF8で出力されるので注意 // Mecabの辞書はUTF8でコンパイルしておくこと import net.moraleboost.mecab.Tagger; import net.moraleboost.mecab.impl.StandardTagger; import net.moraleboost.mecab.Node; import java.io.*; import java.util.*; import java.lang.*; public class cmecab{ public static void main(String[] args) throws Exception{ // 引数が無い場合はヘルプを表示 if (args.length == 0) { System.out.println("使用方法: java cmecab [入力テキストファイル名]"); return; } // バージョン文字列を取得 System.out.println("MeCab version: " + StandardTagger.version()); // 入出力ファイルの設定 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(args[0]), "UTF-8")); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("cmecab-output.txt"), "UTF-8")); String text = ""; while((text = br.readLine()) != null){ // Taggerを構築。 // 第一引数には、MeCabの辞書の文字コードを与える。 // 第二引数には、MeCabのcreateTagger()関数に与える引数を与える。              Tagger tagger = new StandardTagger("UTF-8", ""); // tagger.parse()を呼び出して、文字列を形態素解析する。 // 返されるオブジェクトは、Iterator<String>を実装している。 Node node = tagger.parse(text); // 一つずつ形態素をたどりながら、表層形と素性を出力 while (node.hasNext()) { String surface = node.next(); String feature = node.feature(); bw.write(surface + "\t" + feature +"\n"); } // taggerをクローズ tagger.close(); } br.close(); bw.close(); } } 例:形態素解析して出力される形(「単語<tab>品詞,名詞の形」において「名詞の形」の部分を抽出して上記に書いた値に振り分けたいと思っている。) 70 名詞,数,*,*,*,*,* : 名詞,サ変接続,*,*,*,*,* 1 名詞,数,*,*,*,*,* 何処 名詞,代名詞,一般,*,*,*,何処,ドコ,ドコ 2、1で読み込んだ「単語<tab>文書番号:その文書での単語の出現回数,.........」という形のファイルを読み込んでtfidf値を求め、一行に「単語<tab>tfidf値」という形でテキストファイルに出力していくプログラム tfidfの定義 tf=文書番号Yにおける単語Xの出現確率(出現確率の分母はその文書における単語の合計数) idf=log(文書の合計数/単語Xを含む文書数) よろしくお願いいたします。

  • 単語の頻度プログラム

    英文から単語の頻度を出力するプログラムを作成しています。アルゴリズムは、英文から単語を抜き出して以前にあったものなら、その単語のカウントを1つ増やし、以前にないものなら、新しく頻度表に付け加えるというものです。 とりあえず、isspace関数を使って単語を抜き出すことを考えたのですが、これですと know know, know? のように同じ単語であるのに、カンマやピリオドが付いてしまっていると後で以前に見つかったものかを照合する際に不都合が生じてしまいます。isalnum関数で抜き出したものが、アルファベットか数字であるかを調べ、アルファベットと数字だけを抜き出せば、カンマやピリオドはうまく取り除けると思うのですが。そうすると、I'mなどのアポストロフィーも取り除かれてしまうのではないかと。。 すいません。混乱してます。。皆さんだったらどのようにしますか?答えではなく、ヒントやきっかけを頂けるとありがたいです。

専門家に質問してみよう