2009-07-20 8 views
2

Je suis en train d'analyser un texte scientifique lisible par un humain, principalement dans le domaine de la chimie. Ce qui m'intéresse, c'est de décomposer le texte en une liste de mots, de termes scientifiques (plus de détails ci-dessous) et de signes de ponctuation. Ainsi, par exemple, j'attends le texte "bonjour, monde". casser en 4 jetons: 1) "bonjour"; 2) virgule; 3) "monde" et 4) période. Notez que les espaces ne nécessitent pas de jetons spécialisés.Python: question sur l'analyse de texte lisible par l'homme

Le problème est lié aux "termes scientifiques": ce sont des noms de formules chimiques telles que "1-methyl-4-phenylpyridinium". Quiconque a déjà appris la chimie sait que ces formules peuvent être assez longues et contenir des chiffres, des tirets et des virgules, et parfois même des parenthèses, mais je pense qu'il est raisonnable de supposer que ces belles expressions ne peuvent pas contenir d'espaces. Aussi, je crois que ces expressions doivent commencer par un nombre. Je voudrais que chacune de ces expressions sorte comme un seul jeton. Aujourd'hui, j'utilise l'analyse manuelle pour trouver des «morceaux» de texte commençant par un nombre et se terminant par un espace, un saut de ligne ou un signe de ponctuation suivi d'un espace ou d'un saut de ligne.

Je me demandais s'il y avait une solution intelligente (regex ou autre) que je peux utiliser pour marquer le texte selon les spécifications ci-dessus. Je travaille en Python mais cela peut être agnostique.

Une entrée d'exemple (ne pas tenir compte de toute évidence le contenu ...):..

« Bonjour 1-méthyl-4-phénylpyridinium est ultra-mauvaise Cependant, le 1-méthyl-4-phényl-1,2, 3,6-tétrahydropyridine est pire. "

Exemple de sortie (chaque jeton dans sa propre ligne):

Hello 
. 
1-methyl-4-phenylpyridinium 
is 
ultra 
- 
bad 
. 
However 
, 
1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine 
is 
worse 
. 
+0

Je ne pense pas que vous soyez en train d'affirmer que les noms chimiques commencent par un nombre en attente, voir par ex. cis-2-butène. –

Répondre

2

Cela résoudra votre exemple actuel. Il peut être modifié pour un ensemble de données plus important.

import re 
splitterForIndexing = re.compile(r"(?:[a-zA-Z0-9\-,]+[a-zA-Z0-9\-])|(?:[,.])") 
source = "Hello. 1-methyl-4-phenylpyridinium is ultra-bad. However, 1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine is worse." 
print "\n".join(splitterForIndexing.findall(source)) 

Le résultat est:

""" 
Hello 
. 
1-methyl-4-phenylpyridinium 
is 
ultra-bad 
. 
However 
, 
1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine 
is 
worse 
. 
""" 

Désolé n'a pas vu ultra-mauvais. S'il est nécessaire pour ces mots à diviser ..

import re 
splitterForIndexing = re.compile(r"(?:[a-zA-Z]+)|(?:[a-zA-Z0-9][a-zA-Z0-9\-(),]+[a-zA-Z0-9\-()])|(?:[,.-])") 
source = "Hello. 1-methyl-4-phenylpyridinium is ultra-bad. However, 1-methyl-4-phenyl-1,(2,3),6-tetrahydropyridine is worse." 
print "\n".join(splitterForIndexing.findall(source)) 

donne:

""" 
Hello 
. 
1-methyl-4-phenylpyridinium 
is 
ultra 
- 
bad 
. 
However 
, 
1-methyl-4-phenyl-1,(2,3),6-tetrahydropyridine 
is 
worse 
. 
""" 
+0

si vous avez besoin de crochets: re.compile (r "(?: [A-zA-Z0-9 \ - (),] + [a-zA-Z0-9 \ -()]) | (?: [,.]) ") –

+0

Regex est la voie à suivre pour cette application: il y en a quelques-uns de la boîte analyseurs syntaxiques mais pour une flexibilité extrême, vous devrez utiliser des expressions régulières. –

0

Il pourrait y avoir une expression régulière analyse ce que vous voulez, mais je ne pense pas que ce sera très lisible/maintenable. Mon conseil serait d'utiliser un générateur d'analyseur comme ANTLR. Je pense que vous devrez jeter l'idée par-dessus bord que vous pouvez faire des descriptions chimiques un seul jeton, beaucoup trop complexe. ANTLR a même un débogueur pour que vous puissiez voir pourquoi il n'analyse pas quelque chose que vous pensez qu'il devrait être, je ne pense pas que ce soit possible en utilisant des regexps.

Cordialement,

Sebastiaan

+1

Il existe des outils très pratiques pour le débogage de regex, comme Regex Buddy. –

+0

strfriend est une autre option si vous ne voulez rien télécharger: http://strfriend.com/ –

0

Je suis d'accord avec Sebastiaan Megens qu'une solution regex peut être possible, mais probablement pas très lisible ou maintenable, surtout si vous n'êtes pas déjà bon avec les expressions régulières. Je recommanderais le pyparsing module, si vous restez avec Python (qui je pense est un bon choix).

Une facilité de maintenance supplémentaire vous sera très utile si vos besoins d'analyse augmentent ou changent. (Et je suis sûr que beaucoup de gens diraient "quand" plutôt que "si"! Par exemple, quelqu'un a déjà commenté que vous pourriez avoir besoin d'une notion plus sophistiquée de ce qui doit être autorisé en tant que nom chimique. changer avant même que vous ayez choisi votre outil!)