Je dois accomplir les tâches suivantes:
Un exemple d'ensemble de données ressemble à ceci:
file = re.sub('<P ID=(\d+)>', '', file) file = re.sub('</P>', '', file)
Un "paragraphe" est défini par l'existence du balises
Ce dont j'ai besoin est de créer une structure de données qui ressemble un peu à ceci (j'imagine que c'est un dict
):
XXX
ou, probablement un dataframe pandas
qui ressemble à ceci:
Collection frequency: {'i': 4, 'have': 3, 'always': 2, 'wanted': 2, 'to': 4, 'try': 2, 'like': 1, 'multiple': 1, 'different': 1, 'rasteraunts': 1, 'not': 2, 'quite': 1, 'sure': 1, 'which': 1, 'kind': 1, 'maybe': 1, 'burgers': 2, 'nice': 1, 'love': 1, 'cheeseburgers': 1, 'too': 1, 'you': 1, 'ever': 1, 'gone': 1, 'a': 1, 'diner': 2, 'type': 1, 'restauraunt': 1, 'every': 1, 'in': 1, 'the': 2, 'country': 1, 'am': 1, 'related': 1, 'rest': 1, 'of': 1, 'these': 1, 'paragraphs': 1, 'at': 1, 'all': 1}
Actuellement, je suis en mesure de trouver la fréquence du contenu sans problème en utilisant le code ci-dessous.
import nltk import string from nltk.tokenize import word_tokenize, RegexpTokenizer import csv import numpy import operator import re # Requisite def get_input(filepath): f = open(filepath, 'r') content = f.read() return content # 1 def normalize_text(file): file = re.sub('<P ID=(\d+)>', '', file) file = re.sub('</P>', '', file) tokenizer = RegexpTokenizer(r'\w+') all_words = tokenizer.tokenize(file) lower_case = [] for word in all_words: curr = word.lower() lower_case.append(curr) return lower_case # Requisite for 3 # Answer for 4 def get_collection_frequency(a): g = {} for i in a: if i in g: g[i] +=1 else: g[i] =1 return g myfile = get_input('example.txt') words = normalize_text(myfile) ## ANSWERS collection_frequency = get_collection_frequency(words) print("Collection frequency: ", collection_frequency)
qui renvoie:
| Word | Content Frequency | Document Frequency | | i | 4 | 3 | | have | 3 | 2 | | etc | etc | etc |
Cependant, je suis en train de supprimer les "titres" d'un paragraphe dans la fonction normalize_text
avec les lignes:
{'i': X Y, 'have': X Y, etc}
car je ne veux pas de P
, ID
, 1
, 2
, 3
à compter dans mon dictionnaire car ce ne sont que des en-têtes de paragraphe. p>
Comment puis-je relier l'occurrence d'un mot à son occurrence dans un paragraphe qui me donnerait les résultats souhaités ci-dessus? Je ne suis même pas sûr de la logique de tenter de créer une telle structure de données.
3 Réponses :
Essayez ceci:
def find_paragraph_occurrences(filepath): with open(filepath, 'r') as f: file = f.read() word_list = normalize_text(file) data = file.replace('</P>','').lower().split('<P ID=') result = {} for word in word_list: result[word] = 0 for p in data: if word in p: result[word] += 1 print(result) return result
Si vous voulez grouper par paragraphe, puis par occurrences de mots:
def find_words(filepath): with open(filepath, 'r') as f: file = f.read() word_list = normalize_text(file) data = file.replace('</P>','').split('<P ID=') result = {} for p in data: if p: result[f'paragraph_{p[0]}'] = {} for word in word_list: result[f'paragraph_{p[0]}'][word] = p[2:].count(word) print(result) return result
C'est encore un peu difficile à lire cependant. Si la jolie impression de l'objet est importante pour vous, vous pouvez essayer d'utiliser un un joli package d'impression a>.
Pour trouver le nombre de paragraphes dans lesquels un mot apparaît:
import re from nltk.tokenize import word_tokenize, RegexpTokenizer def normalize_text(file): file = re.sub('<P ID=(\d+)>', '', file) file = re.sub('</P>', '', file) tokenizer = RegexpTokenizer(r'\w+') all_words = tokenizer.tokenize(file) lower_case = [] for word in all_words: curr = word.lower() lower_case.append(curr) return lower_case def find_words(filepath): with open(filepath, 'r') as f: file = f.read() word_list = normalize_text(file) data = file.replace('</P>','').split('<P ID=') result = {} for word in word_list: result[word] = {} for p in data: if p: result[word][f'paragraph_{p[0]}'] = p[2:].count(word) print(result) return result find_words('./test.txt')
c'est incroyable. Je ne peux pas comprendre comment créer une telle structure. Comment puis-je créer quelque chose d'un peu différent, cependant. Idéalement, je ne voudrais pas rechercher un mot spécifique, mais plutôt compter la fréquence des mots qui existent (c'est-à-dire les résultats de ma fonction normalize_text
). Je cherche à trouver le nombre de paragraphes dans lesquels ils apparaissent chacun, pas nécessairement les paragraphes dans lesquels ils apparaissent (puisque certains fichiers contiennent plus de 20 000 paragraphes). J'ai essayé de refléter ce besoin dans ma question. S'il vous plaît laissez-moi savoir si je ne suis pas clair. Je suis désespéré.
Désolé, je suis lent. J'ai remplacé le ['Cheeseburgers', 'is']
par mon objet de liste mots
et cela fonctionne. Mais, aussi élégant que le format «word»: «paragraph_x»: y_occurrences », il est très difficile à lire. Comment puis-je obtenir à la place le nombre total de paragraphes, pas le nombre total d'occurrences groupe par paragraphe?
vous pouvez échanger les boucles contre
pour ce faire. Une seconde, j'ajouterai une autre mise à jour. J'ai également ajouté une mise à jour en utilisant votre fonction normalize_text
@JerryM. si vous n'aimez toujours pas le format et si les ID de paragraphe commencent toujours par 1, vous pouvez donner à chaque mot un tableau d'occurrences pour chaque paragraphe. Par exemple {"i": [6, 1, 2, 0]}
Merci beaucoup Caleb. J'espère accepter votre réponse comme réponse, et j'ai enregistré toutes les variantes. Est-il possible de compter simplement le nombre de paragraphes dans lesquels un mot apparaît? c'est-à-dire {'i': 3, 'have': 2, etc}
continuons cette discussion dans le chat .
document: Counter({'i': 4, 'to': 4, 'have': 3, 'always': 2, 'wanted': 2, 'try': 2, 'not': 2,'burgers': 2, 'diner': 2, 'the': 2, 'like': 1, 'multiple': 1, 'different': 1, 'rasteraunts':1, 'quite': 1, 'sure': 1, 'which': 1, 'kind': 1, 'maybe': 1, 'nice': 1, 'love': 1, 'cheeseburgers': 1, 'too': 1, 'you': 1, 'ever': 1, 'gone': 1, 'a': 1, 'type': 1, 'restauraunt': 1, 'every': 1, 'in': 1, 'country': 1, 'am': 1, 'related': 1, 'rest': 1, 'of': 1, 'these': 1, 'paragraphs': 1, 'at': 1, 'all': 1}) paragraph: Counter({'to': 3, 'i': 3, 'try': 2, 'have': 2, 'burgers': 2, 'wanted': 2, 'always': 2, 'not': 2, 'the': 2, 'which': 1, 'multiple': 1, 'quite': 1, 'rasteraunts': 1, 'kind': 1, 'like': 1, 'maybe': 1, 'sure': 1, 'different': 1, 'love': 1, 'too': 1, 'in': 1, 'restauraunt': 1, 'every': 1, 'nice': 1, 'cheeseburgers': 1, 'diner': 1, 'ever': 1, 'a': 1, 'type': 1, 'you': 1, 'country': 1, 'gone': 1, 'at': 1, 'related': 1, 'paragraphs': 1, 'rest': 1, 'of': 1,'am': 1, 'these': 1, 'all': 1})
Comment puis-je relier l'occurrence d'un mot à son occurrence dans un paragraphe qui me donnerait les résultats souhaités ci-dessus?
Divisez le processus en deux parties: recherche de paragraphes et recherche de mots
from bs4 import BeautifulSoup soup = BeautifulSoup(text,"html.parser") for para in soup.find_all('p'): tokens = [word.lower() for word in words.tokenize(para.text)] print(tokens) ## col_freq.update(tokens) ## doc_freq.update(set(tokens))Lors de l'analyse, conservez deux dictionnaires: un pour la fréquence de collecte et un pour la fréquence des documents.
d = {word:(col_freq[word], doc_freq[word]) for word in col_freq}Itérer sur les paragraphes; obtenir les mots dans un paragraphe; alimentez les mots dans le dict col_freq, et alimentez un ensemble de mots dans le dict doc_freq
for para in paras.tokenize(text): tokens = [word.lower() for word in words.tokenize(para)] col_freq.update(tokens) doc_freq.update(set(tokens))Combinez les deux dictionnaires.
col_freq = collections.Counter() doc_freq = collections.Counter()
Les collections
ne sont-elles pas indéfinies dans ce sens?
?? oui, j'ai oublié la déclaration d'importation - édition maintenant - thnx
Je voulais m'assurer avant de voter et d'accepter. C'est une excellente idée et c'est exactement ce que je recherchais et répond parfaitement aux exigences (aussi, c'est assez rapide, pourrais-je ajouter).
Bonus: importez les pandas en tant que pd; df = pd.DataFrame (d, index = ('collection', 'document')). T
J'ai tellement à apprendre. C'est incroyable. Je poserai une question si nécessaire, mais cela semble avoir tout ce dont je pourrais avoir besoin. J'espère que c'était une bonne question pour vous
Dès le début de votre question, il semble que vous ayez identifié que vous aviez deux exigences / processus similaires mais distincts, mais que vous avez ensuite rédigé une solution pour l'un d'entre eux sans prévoir l'autre. Peut-être que si vous aviez passé plus de temps à réfléchir aux similitudes et aux différences, vous ne vous seriez pas écrit dans un coin. Parfois, il est utile d'écrire des idées sur papier et de les revoir avant d'écrire un code.
Votre exemple d'ensemble de données est représentatif? Il y aura toujours des balises d'ouverture et de fermeture
P
?Oui. Il est généré à partir d'un rapport que notre société exécute. Je crois qu'il pourrait y avoir le cas où rien n'est dans les balises, mais je n'ai jamais vu cela. Quoi qu'il en soit, les balises elles-mêmes existeront toujours. Je n'ai copié que trois exemples pour en faire un sous-ensemble représentatif, mais il y en a plus de 20000 dans certains fichiers (tous avec des balises ouvertes et fermées) @wwii
Devez-vous utiliser
nltk
?Non, en dehors des deux balles, rien n'est "requis". J'ai utilisé
nltk
parce que c'était facile pour un novice comme moi. @wwii Je peux utiliser ou ne pas utiliser à peu près tout ce que je veux (en supposant que nous n'avons rien à payer)