2011-09-15 2 views
2


私はPythonを学び始めていますが、テキストファイルをインポートし、総単語数をカウントし、特定の段落の単語数を数えます(各参加者によって、 'P1'、 'P2'など)、単語数からこれらの単語(P1など)を除外し、段落を別々に印刷します。私はこのコードを持って@James Hurfordへどのように会話の中の各人の語数を集計するのですか?

ありがとう:

words = None 
with open('data.txt') as f: 
    words = f.read().split() 
total_words = len(words) 
print 'Total words:', total_words 

in_para = False 
para_type = None 
paragraph = list() 
for word in words: 
    if ('P1' in word or 
     'P2' in word or 
     'P3' in word): 
     if in_para == False: 
     in_para = True 
     para_type = word 
     else: 
     print 'Words in paragraph', para_type, ':', len(paragraph) 
     print ' '.join(paragraph) 
     del paragraph[:] 
     para_type = word 
    else: 
    paragraph.append(word) 
else: 
    if in_para == True: 
    print 'Words in last paragraph', para_type, ':', len(paragraph) 
    print ' '.join(paragraph) 
    else: 
    print 'No words' 

私のテキストファイルは次のようになります。

P1: Bla bla bla.

P2: Bla bla bla bla.

P1: Bla bla.

P3: Bla.

私がする必要がある次の部分は、各参加者のための単語を加算されます。私はそれらを印刷することしかできませんが、私はそれらを戻したり再利用する方法を知らない。

私は後で操作することができる各参加者のために、各参加者が言ったすべての単語を合計することに加えて、単語カウントを持つ新しい変数が必要です。

P1all = sum of words in paragraph 

「あなた」または「それ」などを2つの単語として数える方法はありますか?

どのようにそれを解決するためのアイデアですか?

答えて

1

おめでとう話された言葉の数を合計することができます!このポストのすべてが今のところ意味をなさないかもしれませんが、後で役に立つと思われる場合はブックマークして復帰してください。最終的には、スクリプト作成からソフトウェアエンジニアリングに移行しようとする必要があります。ここにいくつかのアイデアがあります。

大きな力には大きな責任があり、Python開発者は、手をつかんで「良い」デザインを実施していない他の言語よりも訓練を受ける必要があります。

トップダウンデザインから始めれば助かります。

def main(): 
    text = get_text() 
    p_text = process_text(text) 
    catalogue = process_catalogue(p_text) 

ブーム!あなたはちょうど全体のプログラムを書いた - 今すぐ戻って空白を記入する必要があります!このようにすると、それほど脅威は少ないようです。個人的には、私は自分自身を非常に大きな問題を解決するのに賢明だとは考えませんが、私は小さな問題を解決するプロです。だから一度に一つのことに取り組むことができます。私は 'process_text'で始めるつもりです。

​​

私はそれらのものはまだ何を意味するのか本当にわからないんだけど、私はそのテキストの問題は、あなたが何かに実行し、操作を意味し、「マップ/削減」と呼ばれるパターンに従う傾向がある知っていると、あなたはそれをクリーンアップ私はいくつかのプレースホルダー関数を入れました。私は必要に応じて戻ってさらに追加するかもしれない。

ここで、 'process_catalogue'と記述します。私は "process_dict"と書いていたかもしれませんが、それは私に不自由なものでした。

def process_catalogue(p_text): 
    speakers = make_catalogue(c_text) 
    s_speakers = sum_words_per_paragraph_items(speakers) 
    t_speakers = total_word_count(s_speakers) 

クール。悪くない。あなたは私とは違うアプローチになるかもしれませんが、アイテムを集約し、段落ごとの単語を数え、すべての単語を数えることが理にかなっていると思いました。

この時点で、残りの機能をバックフィルするために、おそらく1つまたは2つの小さな 'lib'(ライブラリ)モジュールを作っていました。輸入について心配することなくこれを実行できるように、私は1つの.pyファイルにすべてを貼りつけますが、最終的には、これらを分解してよりよく見えるようにする方法を学びます。だからこれをやりましょう。

小さなヘルパー関数aaaand
# ------------------ # 
# == process_text == # 
# ------------------ # 

def bundle_dialogue_items(lines): 
    cur_speaker = None 
    paragraphs = Counter() 
    for line in lines: 
     if re.match(p, line): 
      cur_speaker, dialogue = line.split(':') 
      paragraphs[cur_speaker] += 1 
     else: 
      dialogue = line 

     res = cur_speaker, dialogue, paragraphs[cur_speaker] 
     yield res 


def filter_dialogue_items(lines): 
    for name, dialogue, paragraph in lines: 
     if dialogue: 
      res = name, dialogue, paragraph 
      yield res 

def clean_dialogue_items(flines): 
    for name, dialogue, paragraph in flines: 
     s_dialogue = dialogue.strip().split() 
     c_dialouge = [clean_word(w) for w in s_dialogue] 
     res = name, c_dialouge, paragraph 
     yield res 

# ------------------- # 
# == aux functions == # 
# ------------------- # 

to_clean = string.whitespace + string.punctuation 
def clean_word(word): 
    res = ''.join(c for c in word if c not in to_clean) 
    return res 

だから、明らかではないかもしれませんが、このライブラリは、データ処理パイプラインとして設計されています。データを処理するには、パイプライン処理とバッチ処理があります。バッチ処理を見てみましょう。

# ----------------------- # 
# == process_catalogue == # 
# ----------------------- # 

speaker_stats = 'stats' 
def make_catalogue(names_with_dialogue): 
    speakers = {} 
    for name, dialogue, paragraph in names_with_dialogue: 
     speaker = speakers.setdefault(name, {}) 
     stats = speaker.setdefault(speaker_stats, {}) 
     stats.setdefault(paragraph, []).extend(dialogue) 
    return speakers 



word_count = 'word_count' 
def sum_words_per_paragraph_items(speakers): 
    for speaker in speakers: 
     word_stats = speakers[speaker][speaker_stats] 
     speakers[speaker][word_count] = Counter() 
     for paragraph in word_stats: 
      speakers[speaker][word_count][paragraph] += len(word_stats[paragraph]) 
    return speakers 


total = 'total' 
def total_word_count(speakers): 
    for speaker in speakers: 
     wc = speakers[speaker][word_count] 
     speakers[speaker][total] = 0 
     for c in wc: 
      speakers[speaker][total] += wc[c] 
    return speakers 

これらのすべてのネストされた辞書は少し複雑になっています。実際のプロダクションコードでは、これをいくつかのより読みやすいクラス(テストやドキュメントストリングの追加と一緒に!!)に置き換えていますが、これよりももっと混乱させたくありません!申し訳ありませんが、あなたの便宜のために、全体をまとめました。

import pprint 
import re 
import string 
from collections import Counter 

p = re.compile(r'(\w+?):') 


def get_text_line_items(text): 
    for line in text.split('\n'): 
     yield line 


def bundle_dialogue_items(lines): 
    cur_speaker = None 
    paragraphs = Counter() 
    for line in lines: 
     if re.match(p, line): 
      cur_speaker, dialogue = line.split(':') 
      paragraphs[cur_speaker] += 1 
     else: 
      dialogue = line 

     res = cur_speaker, dialogue, paragraphs[cur_speaker] 
     yield res 


def filter_dialogue_items(lines): 
    for name, dialogue, paragraph in lines: 
     if dialogue: 
      res = name, dialogue, paragraph 
      yield res 


to_clean = string.whitespace + string.punctuation 


def clean_word(word): 
    res = ''.join(c for c in word if c not in to_clean) 
    return res 


def clean_dialogue_items(flines): 
    for name, dialogue, paragraph in flines: 
     s_dialogue = dialogue.strip().split() 
     c_dialouge = [clean_word(w) for w in s_dialogue] 
     res = name, c_dialouge, paragraph 
     yield res 


speaker_stats = 'stats' 


def make_catalogue(names_with_dialogue): 
    speakers = {} 
    for name, dialogue, paragraph in names_with_dialogue: 
     speaker = speakers.setdefault(name, {}) 
     stats = speaker.setdefault(speaker_stats, {}) 
     stats.setdefault(paragraph, []).extend(dialogue) 
    return speakers 


def clean_dict(speakers): 
    for speaker in speakers: 
     stats = speakers[speaker][speaker_stats] 
     for paragraph in stats: 
      stats[paragraph] = [''.join(c for c in word if c not in to_clean) 
           for word in stats[paragraph]] 
    return speakers 


word_count = 'word_count' 


def sum_words_per_paragraph_items(speakers): 
    for speaker in speakers: 
     word_stats = speakers[speaker][speaker_stats] 
     speakers[speaker][word_count] = Counter() 
     for paragraph in word_stats: 
      speakers[speaker][word_count][paragraph] += len(word_stats[paragraph]) 
    return speakers 


total = 'total' 


def total_word_count(speakers): 
    for speaker in speakers: 
     wc = speakers[speaker][word_count] 
     speakers[speaker][total] = 0 
     for c in wc: 
      speakers[speaker][total] += wc[c] 
    return speakers 


def get_text(): 
    text = '''BOB: blah blah blah blah 
blah hello goodbye etc. 

JERRY:............................................. 
............... 

BOB:blah blah blah 
blah blah blah 
blah. 
BOB: boopy doopy doop 
P1: Bla bla bla. 
P2: Bla bla bla bla. 
P1: Bla bla. 
P3: Bla.''' 
    text = get_text_line_items(text) 
    return text 


def process_catalogue(c_text): 
    speakers = make_catalogue(c_text) 
    s_speakers = sum_words_per_paragraph_items(speakers) 
    t_speakers = total_word_count(s_speakers) 
    return t_speakers 


def process_text(text): 
    b_text = bundle_dialogue_items(text) 
    f_text = filter_dialogue_items(b_text) 
    c_text = clean_dialogue_items(f_text) 
    return c_text 


def main(): 

    text = get_text() 
    c_text = process_text(text) 
    t_speakers = process_catalogue(c_text) 

    # take a look at your hard work! 
    pprint.pprint(t_speakers) 


if __name__ == '__main__': 
    main() 

だから、このスクリプトは、このアプリケーションのためにほぼ確実に過剰ですが、ポイントは(疑わしく)読みやすい、保守性、モジュール式のPythonのコードがどのように見えるかを確認することです。これは決してでもコレクションを使用して考えていない良い答え、ある

{'BOB': {'stats': {1: ['blah', 
         'blah', 
         'blah', 
         'blah', 
         'blah', 
         'hello', 
         'goodbye', 
         'etc'], 
        2: ['blah', 
         'blah', 
         'blah', 
         'blah', 
         'blah', 
         'blah', 
         'blah'], 
        3: ['boopy', 'doopy', 'doop']}, 
     'total': 18, 
     'word_count': Counter({1: 8, 2: 7, 3: 3})}, 
'JERRY': {'stats': {1: ['', '']}, 'total': 2, 'word_count': Counter({1: 2})}, 
'P1': {'stats': {1: ['Bla', 'bla', 'bla'], 2: ['Bla', 'bla']}, 
     'total': 5, 
     'word_count': Counter({1: 3, 2: 2})}, 
'P2': {'stats': {1: ['Bla', 'bla', 'bla', 'bla']}, 
     'total': 4, 
     'word_count': Counter({1: 4})}, 
'P3': {'stats': {1: ['Bla']}, 'total': 1, 'word_count': Counter({1: 1})}} 
5

I would need a new variable with word count for each participant that I could manipulate later on

いいえ、あなたは、ワードカウントにマッピング人数(defaultdict(int)使う他、Pythonの2.7以降)をCounterが必要になります。

from collections import Counter 
#from collections import defaultdict 

words_per_person = Counter() 
#words_per_person = defaultdict(int) 

for ln in inputfile: 
    person, text = ln.split(':', 1) 
    words_per_person[person] += len(text.split()) 

words_per_person['P1']text.split()があなたの目的のために十分良いトークナイザであると仮定すると、P1の単語の数が含まれています。 (言語学者は、の定義については、の定義に同意しないので、常に近似を得ることになります)。

+0

かなり確信して出力は次のように見えます。 :) –

+0

私はそれを実行し、エラーが発生しました:行59、 人、テキスト= ln.split( ':'、1) ValueError:アンパックするには2つ以上の値が必要です。私は何を間違えたのですか?私はそのエラーについてのスレッドを読むが、助けにはならなかった:/ – epo3

+0

これは ':'を含んでいない行があることを意味する。 –

1

これは2つの変数で行うことができます。誰が話しているのかを把握し、もう1つは話している人のために段落を保持する。段落を格納し、それが誰であるかを関連付けるためには、人物をキーとして辞書を使用し、この人物がこのキーに関連すると述べた段落のリストを使用する。ここから

para_dict = dict() 
para_type = None 

for word in words: 
    if ('P1' in word or 
     'P2' in word or 
     'P3' in word): 
     #extract the part we want leaving off the ':' 
     para_type = word[:2] 
     #create a dict with a list of lists 
     #to contain each paragraph the person uses 
     if para_type not in para_dict: 
      para_dict[para_type] = list() 
     para_dict[para_type].append(list()) 
    else: 
     #Append the word to the last list in the list of lists 
     para_dict[para_type][-1].append(word) 

あなたは、Pythonであなたの冒険を始める上でこれ

for person, para_list in para_dict.items(): 
    counts_list = list() 
    for para in para_list: 
     counts_list.append(len(para)) 
    print person, 'spoke', sum(counts_list), 'words' 
関連する問題