質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

484閲覧

python 多重リストについて

---stax---

総合スコア148

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/05/10 02:07

表題の件について質問させてください。
あるテキストファイルを形態素解析を行い、解析を行ったデータの出現頻度を調べたいと考えています。
しかし実行すると
TypeError: unhashable type: 'list'
というエラーが発生します。

python

1from janome.tokenizer import Tokenizer 2from gensim.models import word2vec 3from sklearn.decomposition import PCA 4from sklearn.manifold import TSNE 5import matplotlib.pyplot as plt 6import matplotlib 7import logging 8import sys 9import re 10import numpy as np 11from collections import Counter 12import operator 13 14word=[] 15word_dic = [] 16 17#--------------------------------------------------------------関数 18 19## 分かち書き(janome使用) 20# Tokenizerのインスタンス生成 21t = Tokenizer() 22# 文字列型を引数とする 23def extract_words(text, fp=sys.stdout): 24 25 #tokenizeメソッドに文字列の引数を渡して形態素解析を行う,tokensはlist型 26 #中身は。区切りした文が形態素解析された状態で入っている 27 #うとうととして目がさめると女はいつのまにか、隣のじいさんと話を始めている。 28 #⇒['うとうと', 'と', 'し', 'て', '目', 'が', 'さめる', 'と', '女', 'は', 'いつのまにか', '、', '隣', 'の', 'じいさん', 'と', '話', 'を', '始め', 'て', 'いる'] 29 tokens = t.tokenize(text) 30 for token in tokens: 31 fp.writelines(token.surface) 32 fp.write("\n") 33 34 #print(tokens) 35 #リスト内包表記を使用して形態素解析されたリストtokensの中身の品詞を、区切りにして原型(引数で受け取ったままの形式)のまま返す 36 return [token.base_form for token in tokens 37 if token.part_of_speech.split(',')[0]] 38 39 40#-----------------------------------------------------------textファイルを開く 41 42# \はエラー、\で表記する 43textfile = open('C:\Users\Desktop\sanshiro.txt') 44# textファイルの内容を読み込む(文字列を返す:str) 45line = textfile.read() 46textfile.close() 47 48 49#-----------------------------------------------------------ファイル整形 50 51# |の除去 52text = line.replace('|','') 53#ルビの除去 54text = re.sub('《.+?》', '', line) 55#入力注の除去 56text = re.sub('[#.+?]', '', line) 57# 空行の削除 58text = re.sub('\n\n', '\n', line) 59text = re.sub('\r', '', line) 60 61#----------------------------------------------------------関数呼び出し 62 63sentences = text.split('。') 64with open("test_token.txt", "w") as fp: 65 wordlist = [extract_words(sentence,fp) for sentence in sentences] 66 67 68#----------------------------------------------------------出現回数表示箇所 69#print(wordlist) 70#countdata = wordlist 71#counter = Counter(countdata) 72#counter.most_common() 73#print(counter) 74

原因がよく分からなかったため試しに以下のコードを実行すると出現回数は表示できていました

python

1from collections import Counter 2 3test = [1,1,1,1,1,1,3,4,5,6,7] 4countdata = test 5counter = Counter(countdata) 6counter.most_common() 7print(counter) 8 9 10#結果 11Counter({1: 6, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1})

そこでエラーの出たコードと見比べるとリストの形が違っていることに気づき、エラーが出ている方はリストがネストされている状態でした

以下エラー発生コードのリスト冒頭

[['うとうと', 'と', 'する', 'て', '目', 'が', 'さめる', 'と', '女', 'は', 'いつのまにか', '、', '隣', 'の', 'じいさん', 'と', '話', 'を', '始める', 'て', 'いる'], ['この', 'じいさん', 'は', 'たしかに', '前', 'の', '前', 'の', '駅', 'から', '乗る', 'た', 'いなか者', 'だ', 'ある'], ['発車', 'ま', 'ぎわに', '頓狂', '《', 'とる', 'きょう', '》', 'だ', '声', 'を', '出す', 'て', '駆け込む', 'で', '来る', 'て', '、', 'いきなり', '肌', '《', 'は', 'だ', '》', 'を', 'ぬく', 'だ', 'と', '思う', 'た', '背中', 'に', 'お', '灸', '《', 'きゅう', '》', 'の', 'あと', 'が', 'いっぱい', 'ある', 'た', 'ので', '、', '三四郎', '《', 'さんする', 'う', '》', 'の', '記憶', 'に', '残る',

このリストはどのタイミングで、なぜネストされた状態になっているのでしょうか?
また、unhashable type: 'list'はリストがネストされているから発生しているということなのでしょうか?
初歩的な質問で申し訳ありませんがアドバイス宜しくお願い致します。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

extract_words関数はリストを返していますが呼出元の[extract_words(sentence,fp) for sentence in sentences]にて、それをさらにリストにしているので2重リストになっています。

Counterの各要素はhashableである必要がありますがlisthashableではありませんので提示エラーが発生しています。ちなみにtuplehashableですが、意図した結果(単語の数を数える)は得られないかと思います。

Python

1from collections import Counter 2#test = [['a','b'],['a','b','c']] # TypeError: unhashable type: 'list' 3test = [('a','b'),('a','b','c')] # tupleはhashableなのでOKだが多分意図した結果ではない。Counter({('a', 'b', 'c'): 1, ('a', 'b'): 1}) 4counter = Counter(test) 5print(counter)

結局、解決策としてはwordlist = [extract_words(sentence,fp) for sentence in sentences]ではなく

Python

1wordlist = [] 2for sentence in sentences: 3 wordlist.extend( extract_words(sentence,fp))

のように、extract_wordsの結果をそのまま追加していくべきかと思います。

投稿2018/05/10 02:34

can110

総合スコア38233

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

---stax---

2018/05/11 01:21

回答ありがとうございます 返答遅れて申し訳ありません 丁寧な解説ありがとうございます まだまだリストやリスト内包表記の理解が足りていないと感じました def flatten_by_extend(nested_list): flat_list = [] for e in nested_list: flat_list.extend(e) return flat_list countdata = flatten_by_extend(wordlist) のように分解する方法も書いてみましたが、そもそもこうならない処理にするべきですね 頂いたコードを参考に書き直してみます 丁寧な解説ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問