3

我有 1000 多项调查,其中许多包含开放式答复。

我希望能够“解析”所有单词并获得最常用单词的排名(不考虑常用单词)以发现趋势。

我怎样才能做到这一点?有我可以使用的程序吗?

编辑如果第 3 方解决方案不可用,如果我们可以只讨论微软技术,那就太好了。干杯。

4

4 回答 4

9

分而治之。将您的问题分解为许多较小的问题并解决每个问题。

第一个问题:将段落变成单词列表。

你很幸运,因为你不必担心完美。实际上解析自然语言以确定“单词”是什么可能非常困难,但坦率地说,您可能并不真正关心“灯泡”是否具有与“灯泡”相同的语义。由于您特别在寻找常用词(现在,稍后会详细介绍),因此有趣的词正是那些容易识别的词,因为它们出现了很多。

所以,进一步分解这个问题。你想要一个单词列表。首先获取一个包含文本的字符串:

StreamReader streamReader = new StreamReader(@"c:\survey.txt");
string source = streamReader.ReadToEnd();

太好了,不知何故你有一个字符串。现在把它变成一个单词数组。因为您可能想将“Frog”和“frog”视为同一个词,所以将所有内容都设为小写。如何做到这一切?根据空格、换行符、制表符和标点符号拆分小写字符串:

char[] punctuation = new char[] {' ', '\n', '\r', '\t', '(', ')', '"'};
string[] tokens = source.ToLower().Split(punctuation, true); 

现在检查输出。那太可怕了。我们忘记了各种各样的东西。句号、逗号、冒号、分号等等。找出您关心的标点符号并将其添加到列表中。

ToLower 是正确的做法吗?ToLowerInvariant 呢?有时你想强调它;这不是其中之一。ToLower 不一定以一致的往返方式对土耳其小写 I 进行规范化,这一事实不太可能影响您的汇总统计数据。我们不打算在这里精确定位。如果有人说“luxury-yacht”,有人说“luxury-yacht”,如果你忘记用连字符打断,前者可能是一个词。谁在乎?无论如何,连字符的单词不太可能出现在您的前十名中。

下一个问题:计算每个单词的所有出现次数:

var firstPass = new Dictionary<string, int>();
foreach(string token in tokens)
{
    if (!firstPass.ContainsKey(token))
        firstPass[token] = 1;
    else
        ++firstPass[token];
} 

伟大的。我们现在有一个将单词映射到整数的字典。麻烦的是,这是倒退的。你想知道的是出现相同次数的所有单词是什么。字典是键/值对的序列,因此对其进行分组:

var groups = from pair in firstPass
             group pair.Key by pair.Value;

好的,现在我们有了一组单词的序列,每个单词都与它的出现次数相关联。订购它。请记住,组的键是字典的值,即计数:

var sorted = from group in groups
             orderby group.Key
             select group;

你想要前一百名,让我们说:

foreach(var g in sorted.Take(100))
{
  Console.WriteLine("Words with count {0}:", g.Key);
  foreach(var w in g)
    Console.WriteLine(w);
}

你完成了。

现在,这真的是你感兴趣的吗?我认为寻找不寻常的单词或成对的单词可能会更有趣。如果“游艇”和“赛车”这两个词经常一起出现,那就不足为奇了。如果“番茄”和“番茄酱”经常一起出现,也就不足为奇了。如果“番茄”和“赛车”开始同时出现,那么可能会发生一些值得注意的事情。

这需要更深入的分析;如果您对此感兴趣,请阅读贝叶斯定理。

另请注意,这会跟踪单词的原始计数,而不是它们的频率——它们每千个单词出现的次数。这也可能是一个有趣的衡量标准:不仅是这个词出现了多少次,句号,还有它出现了多少次,占文本的百分比。

于 2010-05-20T17:29:32.793 回答
4

NLTK包含大量用于处理自然语言的有用信息。

查看这篇文章(链接自 NLTK 站点),了解构建持久的、网络可访问的频率分布的示例。即使它不是您正在寻找的东西,它也可以帮助您了解如何解决您的问题。

更新

回复:MS 技术,您可以使用 IronPython 在 .NET 上运行 NLTK。请参阅这个相关的 SO 问题

于 2010-05-20T14:15:06.587 回答
0

SharpNLP是一个用于进行 NLP 的原生 .NET 库。我不知道它与 NLTK 相比如何,因为我在谷歌搜索之前从未听说过它。

于 2010-05-20T14:34:55.400 回答
0

您可以使用自定义停用词列表创建文本的 lucene 索引,该列表将跳过常用词。用 Luke 打开 lucene 索引,它会显示索引中的顶级术语。

您可以在索引时启用词干提取,以便将单词分组为其根形式。这将帮助您将同一个单词的不同形式(复数、不同时态等)组合在一起。即“问题、问题、质疑”等将显示为“问题”。这是其他任何方法都无法做到的。

于 2010-05-21T06:08:24.903 回答