从分类的短语列表中提取频率数据

时间:2011-10-02 21:22:46

标签: text wolfram-mathematica

在对文档/过去的列表操作问题进行管理之后,我发现空白 - 许多案例涉及数字,而我正在处理大量文本。

我有一个常见的三字短语(三字母)的排序列表,它出现在大量的文本信息中,通过Mathematica的Partition [],Tally []和Sort []命令生成。我正在操作的数据类型的一个示例(我有数百个这样的文件):

  

{{{wa,wa,wa},66},{{i,love,you},62},{{la,la,la},50},{{含义,生命},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},<<< 38211>>,{{of,an,xke},1}}

我希望能够搜索这个文件,这样如果输入是“生命的意义”,它将返回“42”。我觉得我必须忽略一些显而易见的东西,但在修补过后我在这里碰了一堵砖墙。 Mathematica在其文档中数量很多,这是......好吧,并不令人惊讶。

4 个答案:

答案 0 :(得分:6)

假设您可以以您概述的形式将数据加载到Mathematica中,一个非常简单的事情是创建一个哈希表,其中您的三元组将是(复合)键。这是你的样本(你给出的部分):

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}};

以下是创建哈希表的一种可能方法:

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

现在,我们像

一样使用它
In[16]:= trigramHash["meaning","of","life"]
Out[16]= 42

当然,如果您执行多次搜索,这种方法将非常有用。

修改

如果您有许多文件并希望在Mathematica中有效地搜索它们,您可以做的一件事就是使用上面的散列机制将所有文件转换为.mx二进制Mathematica文件。这些文件针对快速加载进行了优化,并作为要存储的定义的持久性机制。以下是它的工作原理:

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

您使用DumpSave创建.mx文件。因此,建议的过程是将数据加载到Mathematica,逐个文件,创建哈希(您可以使用SubValues索引具有文件索引的特定哈希表),然后将这些定义保存到{ {1}}个文件。通过这种方式,您可以快速加载和快速搜索,并且您可以自由决定在任何给定时间将数据的哪一部分保存到Mathematica中(几乎没有性能损失,通常与文件加载相关)。

答案 1 :(得分:5)

这可能没有Leonid给出的解决方案那么快,但你可以将你的对列表变成一个规则列表。

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;

哪个(如果你愿意)你可以包含一个与Leonid的行为类似的函数

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

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

Out[4]= 42

由于您有一个非常大的对列表,因此可以使用Dispatch加速生成的规则的应用。也就是说,除了使用

定义trigramRules之外,请执行与上述相同的所有操作
trigramRules = Dispatch[Rule @@@ trigrams]

答案 2 :(得分:5)

这是将字符串中的单个单词放入列表的一种方法。

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

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

您可以在案例或其他形式的查询中使用它来获得42结果(非常可疑,那个数字......)

---编辑---

通过“查找”,我想到了Leonid Shifrin所展示的那种机制。我不确定遇到的困难是,或者只是从字符串转换为三元组列表。我(仅)展示了管理后者的方法。

---结束编辑---

---编辑2 ---

评论显示了避免阅读列表的方法。让我说明我欣喜若狂,我设法找到了这种方法。下面是我在原始响应中添加的代码,然后在我意识到有更简洁的代码时被替换。

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"}

底线(几乎字面意思):我可以找到其他人的复杂方法,并且比大多数方法更好。

---结束编辑---

Daniel Lichtblau

答案 3 :(得分:1)

相当古老的问题..但现在我们有Association

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

40

甚至

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

lookup["meaning of life"]
  

42