ここから本文です

文章中の単語の出現頻度について。

kao********さん

2012/2/1922:18:19

文章中の単語の出現頻度について。

日本語の文章(数万~十数万字)に登場する単語(文節レベル)の度数分布を求めたいのですが、自分が今まで使っていたの手法は 対象データ群をソート→同一のキー値を持つものをカウント というものだったので、データ群を配列なりなんなりに一度蓄える必要がありました。しかし今回のようにデータの数が膨大になる時はメモリの関係上同じようにはできそうにありません。

そこで質問なのですが、膨大な単語データ群の度数分布を求めるためのよい方法はありませんか?
ご回答よろしくお願い致します。

この質問は、活躍中のチエリアン・専門家に回答をリクエストしました。

閲覧数:
1,195
回答数:
6
お礼:
500枚

違反報告

ベストアンサーに選ばれた回答

shi********さん

2012/2/1923:22:50

私なら、PerlやRubyの連想配列やPythonの辞書に入らないか試してみるかな。
1行読んで単語に分解し、単語をキーにした連想配列に出現回数を入れる。全部の行を処理するまで繰り返す。
単語の数だけメモリを消費するけど、大した量にはならない気がするので。

質問した人からのコメント

2012/2/21 21:30:07

降参 みなさんご回答ありがとうございましたm(_ _)m

どの方のご意見も大変参考になりましたが、今回はshira3さんの仰る通りソートせずに一行ずつ、解析と出現回数のカウントを、並行して頭からこなしてやれば案外スムーズにいったのでこちらのご意見をBAに選ばせて頂きました。

みなさんまた機会があればよろしくお願いします。

ベストアンサー以外の回答

1〜5件/5件中

並び替え:回答日時の
新しい順
|古い順

leh********さん

リクエストマッチ

2012/2/2120:44:59

従来どおりで大丈夫と思いますよ。
以下参考情報です。
NetBook PC で以下のプログラムを単語総数110万語、単語種類数1万個の
ファイルを読み込ませて実行した時の性能は
ソート時間: list でも vector でも 600ms 弱でした。
(単語レベルのため list でも少し速いだけのようです)
getFreqWords() 時間: 30ms 程度でした。

#include <fstream>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <iomanip>

using std::string;
using std::vector;
using std::list;
using std::cin;
using std::cout;
using std::endl;
using std::ifstream;
using std::istream_iterator;
using std::sort;
using std::pair;
using std::setw;

//typedef vector< pair<string, int> > FREQ_WORDS;
typedef list< pair<string, int> > FREQ_WORDS; // 単語頻度を扱う型を定義

void getFreqWords(FREQ_WORDS &fw, const vector<string> &sv);
void printFreqWords(const FREQ_WORDS &fw);

int main()
{
string src;
cin >> src; // get source file names

ifstream ifs(src.c_str()); // input stream
// sv is a string vecter initialized src input
vector<string> sv((istream_iterator<string>(ifs)), istream_iterator<string>());
sort(sv.begin(), sv.end()); // sort the sv

FREQ_WORDS fw;
getFreqWords(fw, sv);
printFreqWords(fw);

return 0;
}

void getFreqWords(FREQ_WORDS &fw, const vector<string> &sv)
{
pair<string, int> tmp;
vector<string>::const_iterator cit;

fw.clear();
for (cit = sv.begin(); cit != sv.end(); ++cit) {
if (*cit != tmp.first) {
if (tmp.first.size() > 0) {
fw.push_back(tmp);
}
tmp = pair<string, int>(*cit, 1);
} else {
tmp.second++;
}
}
if (tmp.first.size() > 0) {
fw.push_back(tmp);
}
}

void printFreqWords(const FREQ_WORDS &fw)
{
FREQ_WORDS::const_iterator cit;

for (cit = fw.begin(); cit != fw.end(); ++cit) {
cout << setw(6) << cit->second << " " << cit->first << endl;
}
}

ecl********さん

2012/2/2014:34:19

>しかし今回のようにデータの数が膨大になる時はメモリの関係上同じようにはできそうにありません。
とありますが、
>日本語の文章(数万~十数万字)に登場する単語(文節レベル)の度数分布を求めたいのですが、
たった十数万字のどこが膨大なのでしょう、1Gのメモリには5億字まで記憶できます。

プログラムを変更しないですむ方法は簡単ですよ。ファイルをプログラムで処理できるサイズに分割し、求まった度数分布を別プログラムで加算すれば良いだけです。

他の回答者さんたちの回答の方が良いことは確実です。

rhi********さん

リクエストマッチ

2012/2/2006:29:47

/*
0219 221819文章中の単語の出現頻度.c kaogei_at_daさん

文章中の単語の出現頻度について。

日本語の文章(数万~十数万字)に登場する単語(文節レベル)の度数分布を求めたいのですが、自分が今まで使っていたの手法は 対象データ群をソート→同一のキー値を持つものをカウント というものだったので、データ群を配列なりなんなりに一度蓄える必要がありました。しかし今回のようにデータの数が膨大になる時はメモリの関係上同じようにはできそうにありません。

そこで質問なのですが、膨大な単語データ群の度数分布を求めるためのよい方法はありませんか?
ご回答よろしくお願い致します。
*/

1.今までの手法は「全部を配列にストックしてメモリソートし
2.まとまって並ぶ同じキイのカウントを度数分布にする
3.なので今回は十数万字→十万語前後の単語を入れる配列?
4.を設定できるか?ソートの時間は?との悩みと推察
5.配列サイズについては現今のPC、OSではこなせる範囲かと
6.それでも大分巨大ですし、ソートは結構な時間になるかも
7.そこで少し考えると
10.膨大な単語データでも、種類にすればそうはならないのでは?11.単語の種類が十万語前後にはならないでしょう。高々数千?
12.直接カウントできれば、そのオーダーのメモリですみます
13.単語をキイとして、同じ単語のカウントと共に持つ
単方向連結リストを、キイの昇順で、文章を入力、単語分析
しながら構築すれば、必要最小限の長さで度数分布が出来る
のではないか?
14.リストノードに単語文字列を持つと、その最大長さが分った
としても短い単語群については随分無駄になるので、ノード
には文字列のアドレス:ポインタのみもち、対応する文字列
自体はmallocで別に保存すれば、すべて同じ固定サイズの
ノードで構成可能、ノードの構造体は例えば
typedef struct nd {
struct nd *next; // 昇順リスト後続ノードポインタ
char *ky; // キイ単語文字列ポインタ
int frq; // キイ単語出現頻度
}
15.度数降順に度数分布を出力したければ、改めて出現頻度の
降順に配列を作成、ソートするか、またはこれとおなじ
方法で今度は出現頻度の降順に連結リストをもうひとつ
つくればOK

で、旨い具合にできればいいのですが。

当方、今日はゆっくりできず、次は27日の予定なのでソースが用意できても、載せるのはそのときになります。

ana********さん

2012/2/2001:57:30

umi********さん

編集あり2012/2/1922:29:53

DBMSを使うのが、一番頭と手を使わなくて良い方法かと。

この質問につけられたタグ

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる