C# .NET Windows.Forms 词云(标签云)生成器控件






4.91/5 (47投票s)
从一些输入文本生成词云。词云是您文本中使用的一组随机排列的单词。每个单词的大小和颜色表示其使用频率。很少使用的单词很小且颜色较浅。该控件可点击,并允许识别鼠标下的单词。
背景
这个控件的灵感来自于免费的基于网络的词云生成器 Wordle。事实上,该控件是我在 http://sourcecodecloud.codeplex.com 项目的衍生产品。
我非常喜欢 Wordle 产生的可视化效果,但我的目标是编写一个非基于网络的本地解决方案来处理大量敏感数据。我在网上找到了一些组件,但大多数组件在处理文本和可视化效果时性能要么很差,要么布局不符合我的预期。
架构和用法
可视化词云有四个阶段
处理数据,例如文本、HTML 或源代码,并提取相关单词,而忽略其他单词。例如,我实现了三个。TextExtractor
从一些文本字符串中提取所有单词,忽略空格和所有非字母字符。FileExtractor
能够逐行处理大型文本文件。另一个 UriExtractor
获取 URL 内容并尝试清除 HTML 标签和 JavaScript(说实话,我只是把它作为一个展示,它的过滤能力非常有限)。
要使用您自己的数据源,只需实现 IEnumerable<string>
接口或从 BaseExtractor
派生。
统计单词,并忽略黑名单中的单词。
结果是一个枚举,包含术语(单词)对和表示该单词在文本中出现次数的整数。在第一个实现中,我使用 KeyValuePair<string, int>
来表示它们。在这个版本中,我切换到 IWord
接口。
public interface IWord : IComparable<IWord>
{
string Text { get; }
int Occurrences { get; }
string GetCaption();
}
我也转移到 LINQ,放弃了我自己用于单词计数、分组和排序的类。我非常喜欢它们,但使用 LINQ 提高了可读性,降低了复杂性,并缩短了代码。所有这些都以可忽略的微不足道的性能下降为代价,这确实是一笔划算的交易。
IBlacklist blacklist = new CommonWords();
IProgressIndicator progress = new ProgressBarWrapper(progressBar);
IEnumerable<string> terms = new StringExtractor(textBox.Text, progress);
cloudControl.WeightedWords =
terms
.Filter(blacklist)
.CountOccurences()
.SortByOccurences();
布局 – 我使用 QuadTree
数据结构来创建控件图形上单词的非重叠映射。相同的数据结构也用于查询控件,查询某个矩形区域或点下的单词。当需要时,此查询用于仅重绘特定区域,或在单击控件时执行某些操作。因此,知道单击了哪个单词以执行与单词相关的操作非常有用,例如显示统计信息或导航到某个 URL。
private void cloudControl_Click(object sender, EventArgs e)
{
LayoutItem itemUderMouse;
Point mousePositionRelativeToControl =
cloudControl.PointToClient(new Point(MousePosition.X, MousePosition.Y));
if (!cloudControl.TryGetItemAtLocation(
mousePositionRelativeToControl, out itemUderMouse))
{
return;
}
MessageBox.Show(itemUderMouse.Word);
}
配置词云控件
您可以在此控件上更改几件事
您可以更改字体类型和大小。
cloudControl.MinFontSize = 6;
cloudControl.MaxFontSize = 60;
cloudControl.Font = new Font(new FontFamily("Verdana"), 8, FontStyle.Regular);
使用不同的颜色
cloudControl.Palette = new Brush[] {Brushes.DarkRed, Brushes.Red, Brushes.LightPink};
使用不同的布局。目前,已实现两种布局。您可以通过从 BaseLayout
派生或仅通过实现您自己的 ILayout
接口来实现您自己的布局。
cloudControl.LayoutType = LayoutType.Typewriter;
布局和绘制图形的逻辑由 IGraphicEngine
接口严格分离。所以我想在未来把它移植到 WPF 或 Silverlight 应该不是什么大问题。
给专家们
通过深入研究代码,您将发现以下额外功能
- 创建您自己的黑名单 -
IBlacklist
接口或CommonBlacklist
基类。 - 从文件加载黑名单 -
CommonBlacklist.CreateFromFile(...)
方法。 - 分组单词 具有共同的词干,如 - departed, depart, departing。
- 您甚至可以查看其上的统计信息。
致谢
- 感谢 Michael Coyle 撰写的优秀文章:C# 中简单的 QuadTree 实现,https://codeproject.org.cn/KB/recipes/QuadTree.aspx。
- 感谢 Wordle 的创建者 Jonathan Feinberg,感谢他提供的精美云图以及有关其背后算法的提示:http://stackoverflow.com/questions/342687/algorithm-to-implement-something-like-wordle。