Найти - Пользователи
Полная версия: Задача на количественное упоминание слов
Начало » Центр помощи » Задача на количественное упоминание слов
1
Bubunt
Всем привет! Помогите пожалуйста с алгоритмом решения задачи. Цель задачи: найти сколько раз в тексте упоминаются фамилии безухов, ростова, болконский. В задаче предложен код:

Скачиваем текст

 import urllib.request
text=urllib.request.urlopen("http://apetrov.me/assets/war_peace_1.txt").read().decode()
print(text[:80])

Задание №2

Найти сколько раз в тексте упоминаются фамилии безухов, ростова, болконский

Подсказка: необходимо модифицировать функцию map_wordcount для того чтобы она учитывала только нужные нам слова.

 second_names = ['безухов', ....]
def map_wordcount_filter(line):
    for word in line:
        if word in ....:
            yield(word, 1)
lines = ....
result = result = run_mapreduce(lines, map_wordcount_filter, ....)
for key, value in sorted( ....

Что необходимо прописать вместо “…..”. К теме прикрепил документ с самой задачей. Для работы необходим Jupyter Notebook.
py.user.next
  
>>> import re
>>> 
>>> def generate_lines(text):
...     word_re = re.compile(r"[а-яё]+")
...     lines = text.strip().lower().split("\n")
...     result = []
...     for line in lines:
...         result.append(word_re.findall(line))
...     return result
... 
>>> from collections import defaultdict
>>> 
>>> def run_mapreduce(input, map_fnc, reduce_fnc):
...     map_result = defaultdict(lambda: [])
...     for obj in input:
...         for key, value in map_fnc(obj):
...             map_result[key].append(value)
...     reduce_result = []
...     for key in map_result:
...         for key, value in reduce_fnc(key, map_result[key]):
...             reduce_result.append((key, value))
...     return reduce_result
... 
>>> def map_wordcount(line):
...     for word in line:
...         yield word, 1
... 
>>> def reduce_wordcount(word, counts):
...     yield word, sum(counts)
... 
>>> 
>>> second_names = ['безухов', 'ростова', 'болконский']
>>> 
>>> def map_wordcount_filter(line):
...     for word in line.split():
...         if word in second_names:
...             yield word, 1
... 
>>> 
>>> import urllib.request
>>> 
>>> text = urllib.request.urlopen("http://apetrov.me/assets/war_peace_1.txt").read().decode()
>>> 
>>> lines = text.lower().splitlines()
>>> result = run_mapreduce(lines, map_wordcount_filter, reduce_wordcount)
>>> for key, value in sorted(result):
...     print(key, value)
... 
безухов 10
болконский 27
ростова 43
>>>
Bubunt
Спасибо большое! Стал разбирать третье задание. Где необходимо с помощью библиотеки matplotlib построить график распределения частот слов. Нашел вот такую статью. Но может возможно выполнить это задание с меньшим количеством кода?
py.user.next
#!/usr/bin/env python3

from matplotlib import pyplot
import numpy as np

def draw_points():
x = np.array([1, 2, 3, 4, 5])
y = np.array([7, 12, 3, 15, 8])

pyplot.plot(x, y, 'bo')

words = ('', 'word1', 'word2', 'word3', 'word4', 'word5', '')
pyplot.xticks(range(7), words)
pyplot.yticks(range(20))

pyplot.savefig('image.png')

pyplot.show()

def main():
draw_points()

if __name__ == '__main__':
main()

Bubunt
Спасибо Вам! И последний вопрос, если можно. Как построить график по первому закону Ципфа? В первом задании мы измерили количество вхождений каждого слова в текст.

 lines = generate_lines(text)
result = run_mapreduce(lines, map_wordcount, reduce_wordcount)
for key, value in sorted(result, key=lambda x: -x[1])[:5]:
    print(key, value)

Теперь необходимо для этих слов построить график распределения частот. В интернете нашел вот такой код, но его явно нужно изменить для выполнения данного задания.

 #!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
import sys
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt
 
FILENAME = sys.argv[1][0:sys.argv[1].find('.')]
 
WORDS = []
 
with open(sys.argv[1], 'rb') as textFile:
    WORDS = (re.findall(re.compile(r'\w+'), (textFile.read()).lower()))
 
LABELS, VALUES = zip(*list(reversed(sorted(Counter(WORDS).items(), key=lambda x: x[1]))))
INDEXES = np.arange(len(LABELS))
 
plt.plot(INDEXES, VALUES)
 
plt.xlim(-(len(LABELS))*5/100)
plt.ylim(-(max(VALUES)*5)/100)
 
plt.xlabel('Rank')
plt.ylabel('Frequency')
 
plt.grid()
plt.savefig('figures/' + FILENAME + '_zipfs', dpi=500)

Не сочтите за наглость или навязчивость, но мне правда интересно, как правильно.
py.user.next
#!/usr/bin/env python3

from matplotlib import pyplot
import numpy as np

def draw_curve():

pairs = (('word1', 15),
('word2', 13),
('word3', 11),
('word4', 7),
('word5', 2))

words = [i for i, _ in pairs]
freqs = [i for _, i in pairs]

totalnum = sum(freqs)

x = np.arange(len(words))
y = np.array([i / totalnum for i in freqs])
maxy = 1

pyplot.plot(x, y, 'bo')

pyplot.xticks(x, words)
pyplot.yticks(np.arange(0, maxy, 1 / len(freqs)))

pyplot.savefig('image_freq.png')

pyplot.show()

def main():
draw_curve()

if __name__ == '__main__':
main()


Это график вероятностей слов - то есть при взятии такого-то слова с такой-то частотой вероятность встретить его в тексте равна такому-то значению.

Bubunt
Как построить график по первому закону Ципфа?
Там, скорее всего, не закон Ципфа имеется в виду, а просто график должен быть похож на соответствующий закону. Если реальные значения подать, то, может, график и будет соответствовать (каждое слово должно иметь частоту в два раза меньше предыдущего).
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB