Javaでそれぞれの英単語のTFIDFの求め方がわかりません。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,686

manchester

score 5

Javaを独学で勉強中のJava初心者です。Javaで英文テキストファイルを読み込みそれぞれの英単語のTFIDFを表示させるプログラムを作りたいのですが、どうしてもうまくできません。TFのみを作ってみました。
エラーの意味がわかりません。
ファイルの読み込み方がわからないので直接英文を打ち込みました。こちらでは長いので省略しました。
降順表示もしたいです。

import java.util.List;
import java.lang.String;
/**
 * doc 文書
  term 用語
 */
public class TF1 {
    public double tf(List<String> doc, String term) {
        double result = 0;
        for (String word : doc) {
            if (term.equalsIgnoreCase(word))
                result++;
        }
        return result / doc.size();
    }

    public static void main(String[] args) {
   String str  = new String("//*英文");

        String doc2 = str.split(" ");
        double tf1 = tf(str, doc2);
        for(String words : doc2){
            if(!str.equalsIgnoreCase(words)){
                    System.out.print(doc2 + ":");
                    System.out.println(tf1);
                }
        }
    }
}


このようなエラーが出てきます。                               
TF1.java:23: null {5}のtf(java.util.List<java.lang.String>,java.lang.String) TF1は指定された型に適用できません
期待値: 
検出値: java.lang.String,java.lang.String
double tf1 = tf(str, doc2);
^                      ^
エラー1個

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • manchester

    2016/12/19 02:33

    字下げしてみます。TFの関数を作るプログラムとmainでTFを作るプログラムの2パターン作ってみました。編集前の方が良いですか?

    キャンセル

  • KSwordOfHaste

    2016/12/19 02:39

    2つアドバイスがあります。(1)コードの内容を頻繁に変更するのはやめた方がよいです。回答を書いてくれている途中の人がいた場合、無暗に質問を変えると回答者の努力が無駄になります。(2)<code>を押すと```改行```のようになると思いますが、```で挟まれた部分にコードを書いてください。そうしないと字下げできません。字下げは半角スペースで(面倒ですけど)。

    キャンセル

  • tetratail

    2016/12/19 02:45

    String doc2 = str.split(" ");  ×  String[] doc2 = str.split(" "); ◎

    キャンセル

回答 3

+1

java初心者さんと言う事で
お困りのようですので
簡単にアドバイスをさせて頂きます。

>Javaで英文テキストファイルを読み込み
この部分についてですが
javaの場合簡単に実装可能です
指定ファイルからテキストファイルを読み込んで
プログラムで処理をする...と言う形になります。
詳しくは調べたら簡単に出てきますのでぜひお試しください。

>英単語のTFIDFを表示させるプログラム
私が予想した限りでは
この部分はやや難易度が高いと思われますが
調べたらすぐにTFIDFサンプルプログラムが
ネットで見つかりました。

細かい仕様がわかりませんが
簡単に実装可能だと思いますので
詳しくは調べたら簡単に出てきますのでぜひお試しください。

>TFのみを表示させるプログラムでも良いので教えてください。
流れだけでもよいのでお願いします。

これもネット上にサンプルプログラムが
有りますので
ぜひ検索をかけてトレースしてみてください


デバッグの仕方がわからないとか
検索の仕方がわからない等
初心者プログラマーの方は(私も初心者ですが)
まずは解決する方法を調べるのが良いと思います。

近年疑問に思った事は
簡単にネットで検索をかければ出てきますので
流れが教えて欲しいのですが~系の
ご質問でしたらまずは
似たようなプログラムが
あちらこちらに点在していますので
トレースしてみてはいかがでしょうか?

トレースしたうえで
この部分がわからないから
教えて欲しい~等
疑問に思う部分もまた湧いてくると
思います。

その時はまたいつでもご質問ください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/19 02:07

    コメントありがとうございます。検索しどれをトレースしてもどうしてもエラーが出てきてしまいます。
    プログラムを追加したのでどこが間違えているのか指摘お願いします。

    キャンセル

checkベストアンサー

0

以下は文章を複数のファイルに分けて入れて
それをコンソール上で入力し、入力し終わったらendを入力すると
出力ファイルに結果のtf,idf,tfidfが出力されるコードです

import java.util.*;
import java.io.*;

public class SHQ {

    static ArrayList<ArrayList<String>> c = new ArrayList<ArrayList<String>>();

    static ArrayList<String> nam = new ArrayList<String>();

    public static void main(String[] args) {

        try (BufferedWriter bw = new BufferedWriter(new FileWriter("write.txt"))) {// 結果出力ファイル名
            bw.write("start");
            bw.newLine();
        } catch (Exception e) {
        }

        Console co = System.console();
        System.out.print("file name:");
        String st = "";
        while (!(st = co.readLine()).equals("end")) {

            ADD(st);
            nam.add(st);
            System.out.print("file name:");
        }
        System.out.println("end");
        STT();

    }

    static void STT() {

        try (BufferedWriter bw = new BufferedWriter(new FileWriter("write.txt",
                true))) {
            int count = 0;
            for (ArrayList<String> q : c) {
                bw.write(nam.get(count) + "ファイルのtf,idf,tf×idf");
                bw.newLine();
                for (String w : q) {
                    bw.write("単語" + w + "のtf:");
                    int count2 = 0;
                    for (String f : q) {
                        if (f.equals(w))
                            count2++;
                    }
                    bw.write("" + (double) count2 / q.size());
                    bw.newLine();

                    bw.write("単語" + w + "のidf:");
                    int couny = 0;
                    for (ArrayList<String> y : c) {

                        for (String h : y) {
                            if (w.equals(h)) {
                                couny++;
                                break;
                            }
                        }

                    }
                    // System.out.println((double)c.size()/couny);
                    double asd = Math.log((double) c.size() / couny) + 1;
                    bw.write("" + asd);
                    bw.newLine();
                    bw.write("単語" + w + "のtf×idf:"
                            + (Math.log((double) c.size() / couny) + 1)
                            * ((double) count2 / q.size()));
                    bw.newLine();
                    bw.newLine();
                }
                count++;
                bw.newLine();
                bw.newLine();
                bw.newLine();
                bw.newLine();
            }

        } catch (Exception e) {
            System.out.print("allerr");
        }

    }

    static void ADD(String s) {

        ArrayList<String> a = null;

        try (BufferedReader br = new BufferedReader(new FileReader(s))) {
            a = new ArrayList<String>();

            String data = "";

            while ((data = br.readLine()) != null) {

                String[] aa = data.split(" +");

                for (String sd : aa) {
                    a.add(sd);
                }

            }

        } catch (Exception e) {
            System.out.println("err3");
        }
        if (a != null) {
            c.add(a);
        }

    }

質問文のエラーを訂正したものが以下です

import java.util.List;
import java.lang.String;

/**
 * doc 文書 term 用語
 */
public class TF1 {
    public static double tf(String term, String[] doc) {
        double result = 0;
        for (String word : doc) {
            if (term.equalsIgnoreCase(word))
                result++;
        }
        return (double) result / doc.length;
    }

    public static void main(String[] args) {
        String str = "It is a Java beginner who is studying Java by self taught. I'd like to create a program that reads English text files in Java and displays TFIDF of each English word, but I can not do it well by all means. I tried to make only TF. I do not know the meaning of the error. Since I do not know how to read the file, I typed in English directly. I omitted it here because it is long. I also want to display descending order";

        String[] doc2 = str.split(" ");

        for (String words : doc2) {
            double tf1 = tf(words, doc2);
            if (!str.equalsIgnoreCase(words)) {
                System.out.print(words + ":");
                System.out.println(tf1);
            }
        }
    }
}

重複したものを表示させない・降順ソートした表示は以下です

import java.util.*;
import java.lang.String;

/**
 * doc 文書 term 用語
 */
public class TF1 {
    public static double tf(String term, String[] doc) {
        double result = 0;
        for (String word : doc) {
            if (term.equalsIgnoreCase(word))
                result++;
        }
        return (double) result / doc.length;
    }

    public static void main(String[] args) {
        String str = "It is a Java beginner who is studying Java by self taught. I'd like to create a program that reads English text files in Java and displays TFIDF of each English word, but I can not do it well by all means. I tried to make only TF. I do not know the meaning of the error. Since I do not know how to read the file, I typed in English directly. I omitted it here because it is long. I also want to display descending order";

        String[] doc2 = str.split(" ");
 TreeMap<String,Double> c=new TreeMap<>();

        for (String words : doc2) {
            double tf1 = tf(words, doc2);
            if (!str.equalsIgnoreCase(words)) {
        c.put(words,tf1);
            }

        }
System.out.println("重複した単語を表示させない");
    for(String er:c.keySet()){
        System.out.println(er+":"+c.get(er));
    }
 TreeMap<String,Double> c2=new TreeMap<>(new CX(c));
c2.putAll(c);
System.out.println("\n\n降順にソート");

for(String er:c2.keySet()){
        System.out.println(er+":"+c.get(er));
    }
    }


}

class CX implements Comparator<String> {
    private Map<String, Double> map;
    public CX(Map<String, Double>  map) {
        this.map = map;
    }
    public int compare(String key1, String key2) {
        double value1 = map.get(key1);
        double value2 = map.get(key2);
        if(value1 == value2)
            return key1.toLowerCase().compareTo(key2.toLowerCase());
        else if(value1 < value2)
            return 1;
        else
            return -1;
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/19 03:09

    ありがとうございます。ちなみに降順に並べ替えることは可能でしょうか?

    キャンセル

0

コードが提示されましたね。とりあえずは

TF1.java:22: 互換性のない型 
期待値: java.lang.String 
検出値:    java.lang.String[] 

String doc2 = str.split(" ");  //誤り
String[] doc2 = str.split(" "); //こちらが正しい

doc2の型の宣言が間違っているわけです。後の方はその影響で出ていたりしますね。初心者のうちは最初のエラーを直してからコンパイルして・・・というのを繰り返した方がいいかも知れません。変数の型の宣言を間違えていたりするとそれ以降エラーが沢山でてしまうので一度になおそうとしても難しいからです。


追記:降順

変更後のコードではtfメソッドで出現頻度を返すようになってますね。これで単語と頻度が順番に求まりますが、降順に表示するには並べ替え(ソート)をする必要があります。ソートにはいろいろやり方がありますが、単語と頻度のように複数の要素を一塊としたデータをソートする例を挙げます。

追記:
失礼、最初の例は間違ってました。List.sortはComparatorを渡さないといけないのでした。
なお下記の例は動作確認してません。
他の方の回答も参考にして「プログラムのエラーを直す」ことを学んでいただければと思います。

// 単語と頻度を保持するクラスを作る
class WordAndFreq {
  String word;
  double freq;
  WordAndFreq(String word, double freq) {
    this.word = word;
    this.freq = freq;
  }
}
...
// まず頻度を調べながらWordAndFreqをListの要素として蓄積
List<WordAndFreq> list = new List<>();
for (String word : doc2) {
  list.add(new WordAndFreq(word, tf(doc2, word)));
}
// Listをソート
list.sort(new Comparator<WordAndFreq>() {
  @Override
  public int compare(WordAndFreq o1, WordAndFreq o2) {
//  return Double.compare(o1.freq, o2.freq); //昇順
    return Double.compare(o2.freq, o1.freq); //降順
  }
});
// ソート結果を表示
for (WordAndFreq wf : list) {
  System.out.format("%s: %4.1f\n", wf.word, wf.freq);
}
...

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/19 03:08

    引数の順番が逆になってませんか?プログラムは慎重に見直してください。

    キャンセル

  • 2016/12/19 03:16

    逆になっていました。無事おそらくTFが表示できました。ありがとうございます。
    重複した単語を表示させなかったり、ソートで並び替えて表示させることは可能ですか?

    キャンセル

  • 2016/12/19 03:23

    一応ソートの例を載せました。ただし、私の回答よりdec5798さんがおっしゃることの方が大事だと思います。わからないことを全部尋ねる前にご自分で調べてみることが大事です。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.22%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る