

### テキストファイル中の名詞をtf-idfのスコア順に並べたい。

Pythonで、ツイートを格納したテキストをMeCab(+natto)で形態素解析し、抽出した名詞のtf-
idfのスコアを出して並べ替えたいです。コードを走らせた結果、以下のエラーが出ました。  
プログラミングを始めたばかりで頼れる人もおらず、何が起きていて、どのように直せばいいのか本当に分からず、質問させていただきました。  
お知恵をお貸しいただけませんでしょうか？

[code]

    Traceback (most recent call last):
      File "tfidf_test_dataset.py", line 41, in <module>
        tfidf = vectorizer.fit_transform(corpus)
      File "/Users/macuser/Workspaces/jxpress/trendword/.direnv/python-3.7.3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py", line 1652, in fit_transform
        X = super().fit_transform(raw_documents)
      File "/Users/macuser/Workspaces/jxpress/trendword/.direnv/python-3.7.3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py", line 1058, in fit_transform
        self.fixed_vocabulary_)
      File "/Users/macuser/Workspaces/jxpress/trendword/.direnv/python-3.7.3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py", line 970, in _count_vocab
        for feature in analyze(doc):
      File "/Users/macuser/Workspaces/jxpress/trendword/.direnv/python-3.7.3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py", line 352, in <lambda>
        tokenize(preprocess(self.decode(doc))), stop_words)
      File "/Users/macuser/Workspaces/jxpress/trendword/.direnv/python-3.7.3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py", line 256, in <lambda>
        return lambda x: strip_accents(x.lower())
    AttributeError: 'generator' object has no attribute 'lower'
    
[/code]

### 該当のソースコード

[code]

    from natto import MeCab
    import codecs
    import sys
    import re
    from sklearn.feature_extraction.text import TfidfVectorizer
    import numpy as np
    
    with codecs.open("tfidf_test.txt", "r", "utf-8") as f:
        corpus = f.read().split("\n")
    
    mecab = MeCab('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
    
    #if tagger.lang == 'ja':
    for txt in corpus:
        words = mecab.parse(txt, as_nodes=True)
    
        for w in words:
            rm_list = ["RT","https","co"]
            if w.feature.split(",")[0] == "名詞":
                if len(w.surface) >= 2:
                    if not any(rm in w.surface for rm in rm_list):
                        print(str(w.surface))
                    else:
                        print("")
                else:
                    print("")
            else:
                print("")
    
    corpus = [mecab.parse(txt, as_nodes=True) for line in corpus]
    
    vectorizer = TfidfVectorizer()
    tfidf = vectorizer.fit_transform(corpus)
    
    #スコアの表示
    print(tfidf.toarray())
    # テキストの数、出現した単語の数
    print(tfidf.shape)
    
    #並べ替え
    feature_names = np.array(vectorizer.get_feature_names())
    for vec in tfidf:
        index = np.argsort(vec.toarray(), axis=1)[:,::-1]
        feature_words = feature_names[index]
        print(feature_words[:,:10])
    
[/code]

[code]

    自転車やバイクで世界を回っている男性が必死で追いかけてくる子猫と出会い、彼の旅を変えたおはなし
    
    京都吹奏楽コンクール高校生小編成の部で金賞をとることができました！ここまで支えてくださった方々のおかげです沢山の応援ありがとうござました
    
    今年も平谷村役場裏のひまわり畑で撮影しました。撮影した殆どの写真が変顔の自分。いちばんまともな顔の写真を。どこにいるかわかりにくいですが
    
[/code]

### 補足情報（FW/ツールのバージョンなど）

iOS 10.12.6, Python 3.7.3, Atom


CC BY-SA 4.0
2019-08-15T02:41:15.087
57364
2019-10-01T00:58:50.850
35471
question
python 自然言語処理
テキスト中の単語をTF-IDFのスコア順に並べ替えたい


MeCabをpythonから使う場合、mecab-python3を入れて使うことができます。nattoを使う代わりにmecab-
python3を使って修正したスクリプトは以下です。

[code]

    import MeCab
    from sklearn.feature_extraction.text import TfidfVectorizer
    import numpy as np
    
    mecab = MeCab.Tagger('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
    
    corpus = []
    with open("tfidf_test.txt") as f:
        targets = {}
        rm_list = ["RT", "https", "co"]
        for line in f:
            words = mecab.parse(line).split("\n")
            tmp = []
            for w in words:
                w = w.strip().split()
                if len(w) == 2:
                    tmp.append(w[0])
                    if w[1].startswith("名詞,"):
                        targets[w[0]] = True
            corpus.append(' '.join(tmp))
    
    print(targets)
    
    vectorizer = TfidfVectorizer()
    tfidf = vectorizer.fit_transform(corpus)
    
    #スコアの表示
    print(tfidf.toarray())
    # テキストの数、出現した単語の数
    print(tfidf.shape)
    
    #並べ替え
    feature_names = np.array(vectorizer.get_feature_names())
    for vec in tfidf:
        index = np.argsort(vec.toarray(), axis=1)[:, ::-1]
        feature_words = feature_names[index]
        print([x for x in feature_words[0] if x in targets][:10])
    
    
[/code]

tfidf vectorizerのfit_transformに渡すべきなのはstr型データのリストです。

nattoによってトーカナイズされたコーパスは、明らかにstr型にはなっていません。

これを、純正のmecab-
python3を使うように変更し、-Owakatiオプションを付け足すことで、単純な分かち書きをstr型として渡すことができます。ただ、この場合は何度もトーカナイズするのは効率が悪いので、一度のトーカナイズですべてできるため、あえて-
Owakatiオプションを使わないで実行しています。

> AttributeError: 'generator' object has no attribute 'lower'

このエラーからもわかるように、fit_transformに渡すリスト内の要素はlower関数をもつ必要があります。lower関数を持っているのはstr型のデータです。

出力は以下のようになりました。

[code]

    (略)
    ['世界', 'おは', '子猫', '必死', 'バイク', '男性', '自転車', 'どこ', '高校生', 'ざま']
    ['高校生', '応援', 'おかげ', 'ここ', 'こと', 'ざま', '金賞', '吹奏楽コンクール', '京都', '方々']
    ['撮影', '写真', '平谷村役場', 'ひまわり畑', '今年', 'どこ', '変顔', 'まとも', 'いちばん', '自分']
    
[/code]


CC BY-SA 4.0
2019-09-30T01:30:45.240
59346
2019-10-01T00:58:50.850
2019-10-01T00:58:50.850
57364
answer