概述
数据分析中一个渐趋普遍的趋势是将相互关联的数据作为网络进行分析。网络分析不仅仅是查看数据的属性,还会关注数据和最终产出之间的结构关联。我们的重点是理解这些网络。网络总是难以进行可视化和导航,而且最大的问题是很难找到与任务相关的模式。
分析师的角度
网络分析师注重研究不同因素之间的关系而非具体因素;
这些因素可以解释社会、文化和经济现象,但它们之间如何联系和它们本身一样重要。在出现社交网络分析观点之前,很多分析师主要注重于内在的个别属性和被忽略的社会行为,也就是说,注重于个别因素如何交互以及它们之间的影响。借助来自社交网络社区的更为新型的技术,分析师可以发现结构中的模式,见证资源或消息流在网络中的传输,理解个别因素如何受到周围环境的影响。
复杂网络下的思考
**在实践中,社交网络可视化是混杂的,尤其当网络规模很大时。**可视化在充分利用人类强大的感知能力上很有用,**但是混乱的展现方式、边重叠以及不合法的节点标签通常会削弱可视化探索的价值。**在这种情况下,交互技术对于理解这些复杂的静态可视化是有用的。内在属性是存在于数据集中的属性,比如性别、种族、薪水或受教育程度。通过节点和边的内在属性进行缩放、平移或过滤等交互可以简化复杂的可视化。不幸的是,对于复杂的网络,这些技术所能达到的可能也就仅此而已,无法挖掘出整个事件,尤其是在小世界网络中密度高的连接很少会没有交叉。内在属性缺乏对社交网络分析师而言非常重要的结构化拓扑信息。**我们的主要贡献是通过反映用户任务的计算属性来增强信息可视化。**计算属性可以通过以下几种策略计算:
- 相关的重要性统计指标(如度或距离中心的程度);
- 聚类算法
- 数据挖掘
随着每个关系的数据维度的增加,社交网络数据会变得极端复杂。大规模的网络可视化通常是节点和边的交叉集合,而且几乎无法看到每个节点以及可以通过它的边到达所有其他的节点。网络可视化可能会提供聚类和游离的信息,但是总体而言,人们很难从这些复杂的可视化中得出更深入的感悟认知。
- 原因1:很难使用单纯的统计方法找到模式和趋势。
- 原因2:网络可视化往往只是提供很少的见解,通常几乎无法提供任何的实用功能。
该怎么做
因此,一名社交网络的研究人员应该做哪些事情**?以紧密结合的方式同时利用可视化和统计技术。“总体概览为先,缩放和过滤次之,最后按需提供细节“,可以作为社交网络分析师组织复杂任务的一个指南。**分析师首先需要分析清楚网络的总体概览,此时需要同时利用统计技术和可视化技术。整个网络的衡量标准,如密度、直径和组件个数,是通过有向布局图进行计算和展示的。该可视化能够使用户对网络的结构、网络中包含的聚类以及网络的深度有一个认识,而统计提供了用于确认和量化视觉发现的一种方式。
一个更专业的分析师会希望对网络中的各个元素的有更深入的了解。用户可以应用在社交网络分析中常见的统计指标来衡量节点、边。
虽然分析师通过统计方法和可视化展现可以了解全局趋势,但是他们的分析通常是不完整的,没有理解单个节点所代表的涵义。
18世纪苏格兰哲学家David Hume写道:
美不是存在于事物本身的品质中。她只存在于对美进行思考的人们的心目之中;而且每个人看到的美都是不同的。
学术的局限性
学术软件项目往往会从一个初始想法有机性底发展成复杂、难以使用的项目,从而可以显得足够新颖,用于发表论文。一些特征通常是在最后一分钟才被添加,其目的仅仅是为了能够给论文“润色“,而几乎不考虑如何集成这些特征或者如何改变程序的基础架构以适应这些特征。
**结果是很多程序都是被杂乱地拼凑在一起,bug很多而且坦白说看起来很让人尴尬。**结果是这些软件并没有和论文一起发布,这导致产生一个最根本的可视化问题:再生性在理论上是可能的,而在实践中很少能够做到。
**解决这种问题的最佳模式是尽可能早地发布软件,然后再不断完善和重构它,这样软件可以反映项目的全局设计目标。**然后,很少有这么做的,因为重新实现没有带来什么学术价值。相反地,人们的做法是启动下一个项目。
学术界很注重创新,但是确实存在情况使得思想可以随着时间不断发展,这样思想才会更清晰更完善。结果不仅仅是对问题和技术有更好的理解,而且可以为用户提供更好的工具,可以易于理解和提供洞察。
案例-奥地利电子媒体艺术奖
奥地利电子媒体艺术奖成立30周年,对过去22年以来提交给该奖项的所有作品进行可视化分析:
项目负责人提出需要从3个不同的角度来审视艺术节:
- 定量分析(对社会现象的数量特征、数量关系与数量变化进行分析的方法)
我们是否可以通过查看过去几年的提交作品来审视艺术节?不同的分类之间有何不同、这些作品来自哪里以及作品的价值随着时间的推移是如何变化的? - 社交网络
在过去那些年,评委团成员都是谁?他们以及获奖人是如何相互联系的? - 艺术历史背景
获奖项目有哪些影响?它们在哪里被引用以及它们在媒体艺术领域产生了什么样的影响?
相关阅读:
作者认为:"可视化工作是信息美学"的新兴取向的一部分。信息可视化作为一门学科,通常涉及一般的视觉映射方法以及对生成的结果可视化的可读性和可理解性的优化。信息美学是基于该领域构建的。然后,当作为一门设计学时,信息可视化力求找到一种基于特定数据集的信息感性化的展现方式。这种展现方式不仅在显式数据展现层次上是可用和可读的,而且增加了设计的“命题密度”。简言之,它表示可视化中深层的形象特征,是可视化展现的“言外之意”。**“信息美学”**这门学科就是以这种方式介于传统的信息可视化、用户界面设计和美学学科之中。
#案例-操作流简述
##《纽约时报》的一天
思考:
你是否曾经想过《纽约时报》网站的读者会涵盖什么类型的人?
你是否想过他们倾向于在一天中的什么时候来访问网站,使用什么工具访问以及他们都来自哪里,纽约、巴黎或博伊西?以及从他们是谁到什么时候、以什么方式以及为什么等。
《纽约时报》研发实验室,从非常简单的基于地理的数据集合开始,很快就深入到海量数据和潜在可视化。最终,创建了一个可视化用于显示每天《纽约时报》网站和手机移动网站在世界和美国的流量。
探索分为以下几个阶段:
- 数据收集(需要筛选与可视化信息);
- 创建一个基于地图的可视化(显示流量模式以及在过去24小时内web站点和移动站点的读者数量的波动)
在上述阶段完成后,发现nytimes.com在晚上是相对活跃而,而午夜到早上5点用户访问量几乎保持不变。当住在美国东海岸的读者陆续醒来时,流量就开始暴涨,可视化开始膨胀;类似地,在人们在中午吃饭休息期间开始查看每天消息时,也会出现类似的流量暴涨。
###接下来,我们还能做很多事情。例如:
- 在一些重大新闻事件发生的时刻,能够自动渲染视频;
- 数据收集和可视化编码方面还有很大的优化空间;
- 以及如何对更为具体的数据进行可视化。例如,显示每天来自特点设备(如IPhone)的流量,或者抽取出位于加州的用户,对他们阅读的新闻进行地理编码,进而就可以分析他们是更倾向于查看关于纽约的新闻还是倾向于查看和他们自己的位置更为接近的新闻。
- 再例如在重大时间或重大新闻时可视化读者的阅读模式,从而了解新闻时如何在web、社交网络和特定地理位置之间传播的。
##1.数据相关操作
###收集数据
基于我们需要创建一个在一天内网站的访问次数并且是基于地理信息的可视化,我们需要收集一下数据:
- 在24小时内,用户每次访问Web站点或收集网站的时间戳;
- 每个用户每次访问时所处位置的经度与维度;
数据清洗
由于访问日志中包含了用户访问web站点和手机站点的很多信息,但是其中很多信息在目前对我们是无用的,因此需要把他们从日志信息中过滤掉。
另外,日志中并不包含每个用户每次访问时的经纬度信息,因此需要在日志“清洗”过程中需要添加该信息;
数据清洗时常见的一个步骤。对于可视化以及其他日志数据的分析,我们只对来自人们在web页面和手机网站的点击数感兴趣,而不是来自网络爬虫、机器人、抓取程序。
为了过滤这些不必要的数据,我们通过可以代码用于识别非人工的访问日志并将其从日志中删除。
在对数据进行清洗过程中,还需要执行对用户的IP地址进行转换成经纬度,从而得到每个访问用户的精确位置。这一点我们可以通过商业数据可来实现(如GeoIp数据库以及其他一些数据库)。
由于原始的访问日志的收集、存储和清理方式,新清洗完的数据是存放在多个文件中的,需要对它们排序之后合并到一个结果文件中去,该文件包含了可视化所需要的数据。
Python、Map/Reduce和Hadoop
到了数据处理的最后一步,我们用Python创建一个简单的map/reduce脚本,该脚本能从清洗后的日志中过滤掉所有不需要的数据,并输出以逗号为分隔符的数据,最后还会对数据进行排序。
(**注:**通常我们可以使用Python来收集、处理和解析数据。当对大的数据集进行可视化时,我们用Python来处理繁重的数据处理,创建在可视化应用程序中易于读取和解析的文件)
接着,使用Amazon的弹性MapReduce Web服务,该服务允许我们在很多基于Hadoop的EC2的运行实例中运行Python实现的map/reduce。
Amazon的EC2运行实例的“配置”不同(分为“低中高”配),不同配置会提供不同的RAM、CPU核数和内存。在很多EC2实例中试验运行map/reduce代码,能帮助我们找到性价比最好的配置。
map/reduce(Hadoop)Job的输出结果是很多有序的文件,这些会文件保存在Amazon的buckets中。我们需要做的是将这些我们下载下来,然后按照期望的方式进行排序与归并,把它们保存在一个文件中。
至此,可视化的准备工作已经完成。
##2.可视化工作
首先,我们先尝试着创建一张世界地图,在一天中地nytimes.com的每次访问用一个小的黄色圆圈表示,对mobile.nytimes.com的每次访问用一个小的蓝色圆圈表示。另外创建一个聚焦于美国的视图。
###可视化工具
Processing选为可视化工具。我们需要将网站的访问用户的经纬度信息映射到Processing中的二维可视化图形中。通过IP转换到经纬度得来的x,y坐标传递给Processing的绘图API,来定位每个用户的位置。
###基础层地图
通过收集到的经纬度值,我们可以初步绘制出用户位置的世界地图上的状况,从而大体地勾画出轮廓,也就是基础层地图。
###发现问题
- 没有具体比例。
日志文件中出现的每个地理位置在我们地图上都是使用相同大小的点表示的。为了能够表示比例,需要基于与某个位置关联的用户量来调整每个位置的可视化表示。 - 其次,黄色点(web站点流量)与蓝色点(手机网站流量)大小相同,而在绘制时,如果两种点击类型出现在同一个地址位置时,就会出现覆盖问题。
- 访问时长问题。起始阶段中,我们没有考虑人们在web站点或手机网站上每次访问或页面查看所花费的时间,只是简单地在地图上为每次访问绘制一个点。这样,就没有人会注意到在某些大城市《纽约时报》有持续大的流量,而在一些小的地区我们可能一天只看几次,这种方式会使我们错误地认为这些地区整天都有流量。对于,访问时长(访问生命周期)问题,我们让每个点在某个时间内淡出,最后在每个点到达生命周期时,它们从内存中删除,并从地图上删除相应的点。
进一步处理数据
之前使用map/reduce脚本从原始访问日志中解析出我们需要的数据,并基于时间对数据进行排序。
现在,需要对每分钟、每个地理位置的所有点击进行计数,输出结果数据并根据访问时间进行排序。
(**注释:**map/reduce是一个编程模型,支持海量数据处理。其处理过程分成两个任务:mapping(映射)和reducing(规约)。Mapper通常是接收一些输入,如日志文件,对数据做一些较小的处理,然后以键值对(key/value)的方式输出数据。Reduce的任务是接收Mapper的输出结果数据,对数据进行归并或规约,通常生成较小的数据集。)
例如:
Timestamp of the access (in HH:MM format),latitude,longitude 1 //key是以逗号作为分隔符,Timestamp of the access(in HH:MM format),latitude,longitude都是key; //value 是1
然后Reducer逐行读取Mapper的输出,保存每分钟每个地理位置的点击计数值。一次,Reducer把Mapper输出的每个“Key”存储到一个Python字典中,每次遇到Mapper的输出有相同的“Key”,就把其在字典中的计数值增加1.
Python字典示例如下:
{ "12:00,40.7308,-73.9970": 128, "12:01,40.7791,-122.4200": 45, ... }
一旦Reducer读取了Mapper的所有的数据输入,基于Key,它对数据进行排序,然后输出排序结果。运行完map/reduce脚本后,我们会得到了一份更准确的数据集。
Mapper与Reducer的.py代码如下:
# Mapper.py import sys for line in sys.stdin: #remove leading and trailing whitespace line = line.strip() #split the line into words words = line.split('\t') try: # output the following: # time(HH:MM),latitude,longitude 1 time = words[1] hours,mins,secs = time.split(":") t = hours+":"+mins print '%s,%s,%s\t%s' % (t, words[44],words[45].1) except Exception: pass
# Reducer.py from operator import itemgetter import sys locations = {} # input comes from STDIN for line in sys.stdin: #remove leading and trailing whitespace line = line.strip() # parse the input we got from Mapper.py key, count = line.strip() try: #update the count for each location #per minute of the day count = int(count) locations[key] = locations.get(key,0)+count except Exception: #count was not a number or some other error, #so silently ignore/discard this line pass #sort the data and then output sorted_locations = sorted(locations.items(),key=itemgetter(0)) for key,count in sorted_locations: try: time,lat,lng = key.split(',') print '%s,%s,%s,%s'% (time,lat,lng,count) except Exception: pass
其他相关案例:http://nytlabs.com/