5 votes

Extraction de données de fréquence à partir d'une liste triée de phrases

Après avoir parcouru la documentation et les questions précédentes sur les opérations de liste, je n'ai rien trouvé - de nombreux cas concernent des nombres, alors que je travaille avec de grandes quantités de texte.

Je dispose d'une liste triée d'expressions courantes de trois mots (trigrammes) qui apparaissent dans un grand nombre d'informations textuelles, générées par les commandes Partition[], Tally[] et Sort[] de Mathematica. Un exemple du type de données sur lesquelles je travaille (j'ai des centaines de ces fichiers) :

{66, Je t'aime, 62, La, la, la, 50, Signification de la vie, 42, Viens, viens, viens, 40, Viens, viens, viens, 40, Ouais, ouais, ouais, ouais, 38, Non, non, non.., 36}, {{on, va}, 36}, {you, love, me}, 35}, {{in, love, with}, 32}, {{the, way, you}, 30}, {{i, want, to}, 30}, {back, to, me}, 29}, <<38211>>, {{of, an, xke}, 1}

J'espère pouvoir effectuer une recherche dans ce fichier de sorte que si l'entrée est "sens, de, la vie", il renvoie "42". J'ai l'impression d'avoir oublié quelque chose d'évident, mais après avoir bricolé un peu, je me heurte à un mur. La documentation de Mathematica contient beaucoup de chiffres, ce qui n'est pas surprenant.

6voto

Leonid Shifrin Points 19822

En supposant que vous pouvez charger vos données dans Mathematica sous la forme que vous avez décrite, une chose très simple à faire est de créer une table de hachage, où vos trigrammes seront les clés (composées). Voici votre échantillon (la partie que vous avez donnée) :

trigrams = {{{"wa", "wa", "wa"}, 66}, {{"i", "love", "you"}, 62}, 
 {{"la", "la", "la"}, 50}, {{"meaning", "of", "life"}, 42}, 
 {{"on", "come", "on"}, 40}, {{"come", "on", "come"}, 40}, 
 {{"yeah", "yeah", "yeah"}, 38}, {{"no", "no", "no"}, 36}, 
 {{"we", "re", "gonna"}, 36}, {{"you", "love", "me"}, 35}, 
 {{"in", "love", "with"}, 32}, {{"the", "way", "you"}, 30}, 
 {{"i", "want", "to"}, 30}, {{"back", "to", "me"}, 29}, 
 {{"of", "an", "xke"}, 1}};

Voici une façon possible de créer une table de hachage :

Clear[trigramHash];
(trigramHash[Sequence @@ #1] = #2) & @@@ trigrams;

Maintenant, nous l'utilisons comme

In[16]:= trigramHash["meaning","of","life"]
Out[16]= 42

Cette approche sera avantageuse si vous effectuez de nombreuses recherches, bien sûr.

EDIT

Si vous avez de nombreux fichiers et que vous souhaitez les rechercher efficacement dans Mathematica, vous pouvez utiliser le mécanisme de hachage ci-dessus pour convertir tous vos fichiers en fichiers de type .mx des fichiers binaires Mathematica. Ces fichiers sont optimisés pour un chargement rapide, et servent de mécanisme de persistance pour les définitions que vous souhaitez stocker. Voici comment cela peut fonctionner :

In[20]:= DumpSave["C:\\Temp\\trigrams.mx",trigramHash]
Out[20]= {trigramHash}

In[21]:= Quit[]

In[1]:= Get["C:\\Temp\\trigrams.mx"]
In[2]:= trigramHash["meaning","of","life"]
Out[2]= 42

Vous utilisez DumpSave pour créer un .mx fichier. La procédure suggérée consiste donc à charger vos données dans Mathematica, fichier par fichier, à créer des hachages (vous pouvez utiliser la fonction SubValues pour indexer une table de hachage particulière avec un index de votre fichier), puis enregistrez ces définitions dans le fichier .mx des dossiers. De cette manière, vous bénéficiez d'un chargement et d'une recherche rapides, et vous avez la liberté de décider quelle partie de vos données doit rester chargée dans Mathematica à tout moment (pratiquement sans perte de performance, normalement associée au chargement de fichiers).

5voto

Simon Points 12141

Cette solution n'est probablement pas aussi rapide que celle proposée par Leonid, mais vous pourriez simplement transformer votre liste de paires en une liste de règles.

In[1]:= trigrams = {{{"wa", "wa", "wa"}, 66}, {{"i", "love", "you"}, 
    62}, {{"la", "la", "la"}, 50}, {{"meaning", "of", "life"}, 
    42}, {{"on", "come", "on"}, 40}, {{"come", "on", "come"}, 
    40}, {{"yeah", "yeah", "yeah"}, 38}, {{"no", "no", "no"}, 
    36}, {{"we", "re", "gonna"}, 36}, {{"you", "love", "me"}, 
    35}, {{"in", "love", "with"}, 32}, {{"the", "way", "you"}, 
    30}, {{"i", "want", "to"}, 30}, {{"back", "to", "me"}, 
    29}, {{"of", "an", "xke"}, 1}};

In[2]:= trigramRules = Rule @@@ trigrams;

Vous pouvez (si vous le souhaitez) l'emballer dans une fonction qui a un comportement similaire à celui de Leonid.

In[3]:= trigram[seq__String] := {seq} /. trigramRules

In[4]:= trigram["meaning", "of", "life"]

Out[4]= 42

Si vous avez une très grande liste de paires, l'application des règles générées peut être accélérée par l'utilisation de l'option Dispatch . C'est-à-dire, faites tout comme ci-dessus, sauf définir trigramRules en utilisant

trigramRules = Dispatch[Rule @@@ trigrams]

5voto

Daniel Lichtblau Points 6224

C'est une façon d'obtenir les mots individuels de votre chaîne dans une liste.

In[262]:= str = "meaning, of, life"; ReadList[
 StringToStream[str], Word, WordSeparators -> {",", " "}]

Out[262]= {"meaning", "of", "life"}

Vous pourriez l'utiliser dans un Cases ou une autre forme de recherche pour obtenir le résultat 42 (très suspect, ce chiffre...).

--- modifier

Par "look-up", je pense au type de mécanisme montré par Leonid Shifrin. Je n'étais pas sûr de savoir si la difficulté rencontrée était celle-là, ou simplement la conversion de cordes en listes de triades. Je montre (seulement) un moyen de gérer cette dernière.

--- end edit ---

--- edit 2 ---

Un commentaire indique les moyens d'éviter la ReadList. Permettez-moi de dire pour mémoire que je suis ravi d'avoir trouvé cette approche. Voici le code que j'avais mis dans ma réponse originale, puis remplacé lorsque j'ai réalisé qu'il existait un code plus concis.

str = "meaning, of, life";
commaposns = StringPosition[str, ", "];
substrposns = 
  Partition[
   Join[{1}, 
    Riffle[commaposns[[All, 1]] - 1, commaposns[[All, 2]] + 1], {-1}],
    2];
substrs = Map[StringTake[str, #] &, substrposns]

Out[259]= {"meaning", "of", "life"}

En résumé (presque littéralement) : Je peux trouver des approches alambiquées aussi bien que n'importe qui, et mieux que la plupart.

--- end edit ---

Daniel Lichtblau

1voto

george Points 2473

C'est une vieille question mais maintenant nous avons Association

lookup = Association[Rule @@@ trigrams];
lookup[{"come", "on", "come"}]

40

ou même

lookup = Association[
   Rule[StringJoin@Riffle[#1, " "], #2] & @@@ trigrams]

lookup["meaning of life"]

42

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X