你知道吗,你可以把普通的静态ggplot图转换成动画图?在R软件包ganimate的帮助下,你可以做到这一点,而且效果非常好。对所有类型的几何图形都能毫不费力地转化为超级流畅的动画,让我和我的同事印象非常深刻。这篇文章中,我将对ganimate的一些奇妙功能进行简短的概述,我希望你会像我们一样喜欢这些功能!
由于七夕节刚刚过去,我们将探索约会实验数据集。希望我们能了解动态可视化以及如何找到我们的另一半。
约会实验数据集
是什么影响了一见钟情?
数据是从约会活动的参与者那里收集的。在这些活动中,参与者将与其他每个异性参与者进行四分钟的 "第一次约会"。在四分钟结束后,参与者被问及是否愿意再次见到他们的约会对象。他们还被要求在六个方面对他们的约会对象进行评分。吸引力、真诚、智慧、乐趣、有雄心壮志和共同的兴趣。最后,我们想通过比较人们自我报告的评分和实际影响人们决定的因素,来确定人们是否真的知道他们想要什么。
定义基本动画:过渡_*
静态图如何变成动态图?基本上,ganimate创建了数据子集,这些子集被单独绘制,并构成了帧,当连续播放时,就形成了基本动画。
transition_*函数定义了数据子集是如何产生的,从而定义了任何动画的一般特征。在本文中,我们将探讨三种类型的过渡:transition\_states(), transition\_reveal() 和 transition_filter()。我们从头开始吧。
我们将从transition_states()开始。在这里,数据根据提供给states参数的变量的类别被分割成子集。如果一个数据集的几行与同一个观察单位有关,并且应该可以被识别出来,那么需要提供一个定义观察单位的分组变量。
请注意,为了确保这篇文章的可读性,所有关于快速约会数据解释的文字都是用斜体书写的。如果你对这部分不感兴趣,你可以直接跳过这些段落。
首先,我们要探讨快速约会实验的参与者在伴侣中寻找什么。参与者被要求对潜在约会对象中的属性的重要性进行评分,将100分的预算分配给几个特征,数值越高表示越重要。参与者被要求根据他们自己的观点对这些属性进行评分。
我们将绘制所有这些评级(X轴)的所有属性(Y轴)。由于我们想把_自我评分_与_实际影响评分_进行比较,我们将在这两组评分之间进行转换。颜色表示参与者的个人愿望。一个的气泡表示一个的参与者对某一属性的评分。
## 静态图 # ...特征与(假定的)评级... # ...颜色和大小映射到自己的评级,按ID分组 ggplot(df, color = rating, # bubbels总是根据自己的愿望来着色的 group = iid)) + # 不同状态下观察结果的标识符 labs(y = "", # 没有轴标签 x = "100分", # X轴标签 ## 动画图谱 plot1 + transition_states(states = rating) # 根据变量等级,对对比度子集进行动画处理
静态图:
动态图:
首先,如果你有点困惑哪种评分是自我评分和实际评分,我们将在下文探讨动态标签。
显然,不同的人在伴侣身上寻找不同的东西。然而,吸引力往往被优先于其他品质。但在所有属性中,吸引力的重要性在个人之间的差异最大。有趣的是,人们很清楚,他们的约会对象的评价可能与他们自己的观点不同。
因此,我们所有人都有希望,寻找和我们一样有雄心壮志或一样聪明的人。然而,重要的并不总是内在价值。
gganimate允许我们根据自己的意愿来定制动画的细节。通过参数transition_length,我们可以定义从一个数据子集过渡到另一个数据子集所需的相对长度,通过state_length,相对而言,每个原始数据子集的显示时间。只有当wrap参数设置为 "true "时,最后一帧才会被变形回动画的第一帧,形成一个无尽的无缝循环。当然,不同的过渡函数的参数可能有所不同。
## 动画 #...替换默认参数 transition_length = 3, # 总时间的3/4用于转换 state_length = 1, # 1/4的时间用于显示实际数据 wrap = FALSE) # 没有无尽的循环
动态图:
过渡风格
如前所述,ganimate负责计算额外的数据点,以便在实际输入数据的连续显示点之间创造平滑过渡。通过ease_aes,我们可以控制哪个所谓的缓和函数被用来将原始数据点 "变形 "到彼此之间。默认参数用于声明一个图中所有美学的缓和函数。另外,缓和函数也可以通过名称分配给各个美学模型。其中有四维、三维、正弦和指数缓和函数,线性缓和函数是默认的。这些函数可以通过添加修饰词后缀来进一步定制:用-in,函数按原样应用;用-out,函数反向应用;用-in-out,函数在过渡的前半段按原样应用,在后半段反向应用。
在这里我使用缓和函数,模拟球的弹跳。
## 动画
# ......添加特殊的缓和
ease_aes("bounce-in") # 反弹式缓和
动态图:
动态标示。{帧变量}
ganimate提供了所谓的帧变量,提供关于整个动画或前一帧/当前帧/下一帧的元数据。帧变量--当用大括号包括时--在所有图像标签中可用于字符串字面解释。例如,我们可以用定义了当前(或即将)显示的实际数据子集的状态变量的值来标记每一帧。
## 动画
# .添加动态标签:带有状态变量当前/下一个值的副标题
labs(subtitle = "{closest_state}") + # 添加帧变量作为副标题
动态图:
可用的变量集取决于过渡函数。要获得任何动画可用的帧变量列表(默认是最后一个),可以调用 frame_vars() 函数,以获得可用变量的名称和值。
表明先前的数据:shadow_*
为了强调不同帧之间的相互联系,我们可以应用Gganimates的一个 "阴影"。默认情况下,shadow\_null()即没有阴影被添加到动画中。一般来说,阴影以不同的方式显示过去帧的数据点:shadow\_trail()创建一个均匀间隔的数据点的痕迹,而shadow_mark()显示所有原始数据点。
我们将使用shadow\_wake()来创建一个过去数据点的 "唤醒",这些数据点正在逐渐缩小和消失。参数wake\_length允许我们设置wake的长度,相对于总帧数。由于唤醒是重叠的,几何图形的透明度可能需要调整。很明显,对于有很多数据点的图来说,阴影会妨碍其清晰度。
# 与plot1相同,但在geom_jitter中使用alpha = 0.1
shadow\_wake(wake\_length = 0.5) # 添加阴影
动态图:
过渡的好处_*
虽然我只是喜欢动画图的视觉效果,优点是更容易通过动画过渡来追踪单个观察样本。
同样地,例如transition_reveal对时间序列持有额外的价值,它不仅在其中一个轴上映射时间变量,而且还映射到实际时间,让我们快速看一下不同约会活动中 "成功"案例。
## 静态图
#......女性、男性或情侣的事件日期与第二次约会的兴趣对比
aes(x = 日期, # 快速约会事件的日期
y = count, # 对第二次约会的兴趣
color = info, # 哪一组:女性/男性/情侣
title = "第二次约会的总体兴趣")
动态图:
显示的是每次约会后对第二次约会感兴趣的女性和男性的百分比,以及双方都想再见面的情侣的百分比。
大多数情况下,女性比男性对第二次约会更感兴趣。此外,约会伙伴之间的吸引力往往不是双向的:情侣双方都想进行第二次约会的情况比男性和女性的兴趣要少得多。虽然很难确定一年中最浪漫的时间,但根据数据,初秋时节似乎有一种懈怠的浪漫。也许每个人都还在为他们的夏季恋情心碎?
另一个非常方便的选项是transition\_filter(),它是展示你的数据探索中选定的关键见解的一个好方法。在这里,动画浏览了由一系列过滤条件定义的数据子集。由你决定你想要哪个数据子集的阶段。数据是根据transition\_filter()中定义的逻辑语句过滤的。所有语句成立的行都被包含在相应的子集中。我们可以为逻辑表达式分配名称,这些名称可以作为框架变量被访问。如果keep参数被设置为 "true",那么之前的帧的数据将永久地显示在后面的帧中。
我想探讨的是,一个人自身的特点是否与他寻找的伴侣的属性有关。异性相吸吗?
下面显示的是约会参与者对潜在伴侣的不同属性的重要性。对比的是参与者的子集,他们被约会伙伴评为特别有趣、有吸引力、真诚、聪明或有野心。评分标准从1=低到10=高,因此我认为>7的值是相当出色的。
## 静态图
# ...不同属性的重要性评级
aes(x = 变量, # 不同属性
对潜在伴侣的重要性
颜色 = 变量, # 不同的属性
填充 = 变量)) +
## 动画
# ......显示不同子集的参与者的评分
transition_filter("更有吸引力" = Attractive > 7, # 添加命名的过滤器表达式
"不那么有吸引力" = 有吸引力 <= 7
"更有趣" = 有趣 > 7,
"较少乐趣"= 乐趣<=5)
动态图:
当然,特别有吸引力、聪明或有趣的参与者的数量相对较少。令人惊讶的是,低分和高分的参与者在寻找伴侣方面似乎没有什么区别。相反,低分组包括了更多对某些特征有偏离期望的人。个人的品味似乎或多或少独立于个人特征而变化。
数据的外观:enter_ / exit_
特别是当显示的数据子集不重叠或只有部分重叠时,enter_()和exit_()函数是一个很好的方法,它使我们能够设计数据点的进入和退出。有许多可组合的选项:数据点可以简单地(不)出现(默认),淡出(enter\_fade()/exit\_fade()),增长或缩小(enter\_grow()/exit\_shrink()),逐渐改变颜色(enter\_recolor()/exit\_recolor()),飞入和飞出(enter\_fly()/exit\_fly())或漂移(enter\_drift()/exit\_drift())。我们可以用这些风格化的手段来强调不同帧的数据基础的变化。
## 动画
# ......显示不同子集的参与者的评分
transition_filter("更有吸引力" = Attractive > 7, #
"不那么有吸引力" = 有吸引力 <= 7,
"较少乐趣" = 乐趣 <= 5) +
exit_fade() # ...当颜色变淡时
动态图:
微调和保存:animate() & anim_save()
ganimate让我们非常容易地完成和保存我们的动画。我们可以将完成的ganimate对象传递给animate(),除其他外,定义要渲染的帧数(nframes)和/或每秒的帧率(fps)和/或动画应该持续的秒数(duration)。我们还可以定义渲染各个帧的设备(默认是device = "png",但所有流行的设备都可用)。此外,我们还可以定义传递给设备的参数,比如说宽度或高度。
函数anim_save()的工作方式简单明了。我们可以定义文件名和路径(默认为当前工作目录),以及动画对象(默认为最近创建的动画)。
# 创建一个 gganimate 对象 transition_filter("更有吸引力" = 吸引力>7, "不那么有吸引力" = 有吸引力 <= 7) # 将最后创建的动画保存到当前目录中 anim_save("plot.gif")
结论
我希望这篇博文能让你了解如何使用ganimate将你自己的图片升级为漂亮的、内容丰富的动画。
但更重要的是:不要等待爱情。约会的数据显示,很可能有一个人正在寻找和你一样的人。
##爱心动画 plot(heart %>% #包括颜色和像素的x/y位置 geom_point(size = 18, # 取决于动画的高度和宽度 shape = 15) + # 正方形 guide = FALSE) + # 不包括图例