- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在观察 gganimate
中的一些我无法解释的行为,我想了解我做错了什么(或者它是否是一个错误)。
例如,这是一个非常简单的数据集及其绘图:
library(dplyr) # dplyr_0.7.8
library(tidyr) # tidyr_0.8.2
crossing(p = 1:2,
t = seq(0, 1, len = 30),
s = c(0, .5)) %>%
mutate(x = t,
y = t^p) %>%
filter(t > s) ->
Z
library(ggplot2) # ggplot2_3.1.0
Z %>%
ggplot(aes(x,y)) +
facet_wrap(~s) +
geom_point()
正如预期的那样,第二个面 (s=0.5) 只有 x > 0.5 的数据,这(根据 tibble Z 的构造方式)来自 t > 0.5。
如果要对上述数据进行动画处理(使用 t
作为时间),我希望第二个方面在动画的前半部分是空的,然后显示与第一个方面相同的内容下半场。然而:
library(gganimate) # gganimate_1.0.2
Z %>%
ggplot(aes(x, y, group = interaction(p,s))) +
facet_wrap(~s) +
geom_point() +
transition_time(t) +
ggtitle('{frame_time}')
上面的代码生成了一个动画(使用gifski_0.8.6
),它有两个面,其中第二个面只简单地显示它的点,而且在错误的时间显示它们(即在开始的时候)动画)。
我是不是遗漏了什么,或者这是一个错误?
最佳答案
这将是一个相当长的答案,分为 3 个部分。您可以从这里开始查看解释,或向下滚动以查看两个建议的解决方法。
这似乎是 transition_time
的问题, 当它以一个空的 facet 开始时表现得很奇怪。
通过底层代码调试后,我认为问题出在 expand_panel
上。 TransitionTime下的功能.我们可以通过运行 debug(environment(TransitionTime$expand_panel))
来证明这一点在绘制有问题的动画之前。查看以下调试代码中 A-B 行之前和之后发生的情况:
> TransitionTime$expand_panel
<ggproto method>
<Wrapper function>
function (...)
f(..., self = self)
<Inner function (f)>
function (self, data, type, id, match, ease, enter, exit, params,
layer_index)
{
... # omitted
true_frame <- seq(times[1], times[length(times)])
# line A
all_frames <- all_frames[
all_frames$.frame %in% which(true_frame > 0 & true_frame <= params$nframes),
,
drop = FALSE]
# line B
all_frames$.frame <- all_frames$.frame - min(all_frames$.frame) + 1
... # omitted
}
在每个方面面板中,all_frames
是一个数据框,其中包含与该特定方面对应的原始数据行,以及在它们之间传输的其他行。 true_frame
是数据应显示的有效帧的整数向量。
对于第一个面板(即 s = 0),这是 A 行之前的内容:
> true_frame
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
[23] 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
[45] 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
[67] 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
[89] 89 90 91 92 93 94 95 96 97 98 99 100
> head(all_frames)
x y group PANEL shape colour size fill alpha stroke .id .phase .frame
1 0.03448276 0.034482759 1 1 19 black 1.5 NA NA 0.5 1 raw 1
45 0.03448276 0.001189061 2 1 19 black 1.5 NA NA 0.5 2 raw 1
3 0.04310345 0.043103448 1 1 19 #000000FF 1.5 NA NA 0.5 1 transition 2
4 0.04310345 0.002080856 2 1 19 #000000FF 1.5 NA NA 0.5 2 transition 2
5 0.05172414 0.051724138 1 1 19 #000000FF 1.5 NA NA 0.5 1 transition 3
6 0.05172414 0.002972652 2 1 19 #000000FF 1.5 NA NA 0.5 2 transition 3
> tail(all_frames)
x y group PANEL shape colour size fill alpha stroke .id .phase .frame
530 0.9827586 0.9827586 1 1 19 #000000FF 1.5 NA NA 0.5 1 transition 98
629 0.9827586 0.9661118 2 1 19 #000000FF 1.5 NA NA 0.5 2 transition 98
716 0.9913793 0.9913793 1 1 19 #000000FF 1.5 NA NA 0.5 1 transition 99
816 0.9913793 0.9830559 2 1 19 #000000FF 1.5 NA NA 0.5 2 transition 99
434 1.0000000 1.0000000 1 1 19 black 1.5 NA NA 0.5 1 raw 100
871 1.0000000 1.0000000 2 1 19 black 1.5 NA NA 0.5 2 raw 100
all_frames
在 A-B 行之后没有变化,所以我不会再重复控制台打印输出。
另一方面,对于第二个面板(即 s = 0.5),线 A-B 产生了显着差异。这是 A 行之前的内容:
> true_frame
[1] 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
[25] 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
[49] 98 99 100
> head(all_frames)
x y group PANEL shape colour size fill alpha stroke .id .phase .frame
16 0.5172414 0.5172414 3 2 19 black 1.5 NA NA 0.5 NA raw 49
60 0.5172414 0.2675386 4 2 19 black 1.5 NA NA 0.5 NA raw 49
3 0.5241379 0.5241379 3 2 19 #000000FF 1.5 NA NA 0.5 3 transition 50
4 0.5241379 0.2749108 4 2 19 #000000FF 1.5 NA NA 0.5 4 transition 50
5 0.5310345 0.5310345 3 2 19 #000000FF 1.5 NA NA 0.5 3 transition 51
6 0.5310345 0.2822830 4 2 19 #000000FF 1.5 NA NA 0.5 4 transition 51
> tail(all_frames)
x y group PANEL shape colour size fill alpha stroke .id .phase .frame
513 0.9827586 0.9827586 3 2 19 #000000FF 1.5 NA NA 0.5 3 transition 98
617 0.9827586 0.9661118 4 2 19 #000000FF 1.5 NA NA 0.5 4 transition 98
710 0.9913793 0.9913793 3 2 19 #000000FF 1.5 NA NA 0.5 3 transition 99
87 0.9913793 0.9830559 4 2 19 #000000FF 1.5 NA NA 0.5 4 transition 99
441 1.0000000 1.0000000 3 2 19 black 1.5 NA NA 0.5 3 raw 100
88 1.0000000 1.0000000 4 2 19 black 1.5 NA NA 0.5 4 raw 100
true_frames
涵盖范围 50-100,而帧数在 all_frames
从 49 开始。很好,足够接近,我们可以为匹配 true_frames
中的帧的数据帧子集。 & 删除带有 .frame < 50
的行,但这不是行 A 中发生的情况。观察:
> true_frame > 0 & true_frame <= params$nframes # all TRUE
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[20] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[39] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
> which(true_frame > 0 & true_frame <= params$nframes)
# values start from 1, rather than 1st frame number
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
[33] 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
> all_frames$.frame %in% which(true_frame > 0 & true_frame <= params$nframes)
# only the first few frames match the last few values!
[1] TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[16] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[31] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[46] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[76] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[91] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
> all_frames
# consequently, only the first few frames are left after the subsetting
x y group PANEL shape colour size fill alpha stroke .id .phase .frame
16 0.5172414 0.5172414 3 2 19 black 1.5 NA NA 0.5 NA raw 49
60 0.5172414 0.2675386 4 2 19 black 1.5 NA NA 0.5 NA raw 49
3 0.5241379 0.5241379 3 2 19 #000000FF 1.5 NA NA 0.5 3 transition 50
4 0.5241379 0.2749108 4 2 19 #000000FF 1.5 NA NA 0.5 4 transition 50
5 0.5310345 0.5310345 3 2 19 #000000FF 1.5 NA NA 0.5 3 transition 51
6 0.5310345 0.2822830 4 2 19 #000000FF 1.5 NA NA 0.5 4 transition 51
我们现在来到 B 行 ( all_frames$.frame <- all_frames$.frame - min(all_frames$.frame) + 1
),它基本上将帧重新居中以从 1 开始。因此,这就是我们在 B 行之后得到的:
> all_frames
x y group PANEL shape colour size fill alpha stroke .id .phase .frame
16 0.5172414 0.5172414 3 2 19 black 1.5 NA NA 0.5 NA raw 1
60 0.5172414 0.2675386 4 2 19 black 1.5 NA NA 0.5 NA raw 1
3 0.5241379 0.5241379 3 2 19 #000000FF 1.5 NA NA 0.5 3 transition 2
4 0.5241379 0.2749108 4 2 19 #000000FF 1.5 NA NA 0.5 4 transition 2
5 0.5310345 0.5310345 3 2 19 #000000FF 1.5 NA NA 0.5 3 transition 3
6 0.5310345 0.2822830 4 2 19 #000000FF 1.5 NA NA 0.5 4 transition 3
好了:由于 expand_panel
中的 A-B 行,我们得到了问题中描述的现象:第二个面板中的动画从第 1 帧开始,& 只持续了可怜的 3 帧就一起消失了。
因为我们知道是什么导致了问题,我们可以调整 expand_panel
的代码, 并定义一个稍微不同的版本 transition_time
而是使用它:
library(tweenr)
TransitionTime2 <- ggproto(
"TransitionTime2",
TransitionTime,
expand_panel = function (self, data, type, id, match, ease, enter, exit, params,
layer_index) {
row_time <- self$get_row_vars(data)
if (is.null(row_time))
return(data)
data$group <- paste0(row_time$before, row_time$after)
time <- as.integer(row_time$time)
states <- split(data, time)
times <- as.integer(names(states))
nframes <- diff(times)
nframes[1] <- nframes[1] + 1
if (times[1] <= 1) {
all_frames <- states[[1]]
states <- states[-1]
}
else {
all_frames <- data[0, , drop = FALSE]
nframes <- c(times[1] - 1, nframes)
}
if (times[length(times)] < params$nframes) {
states <- c(states, list(data[0, , drop = FALSE]))
nframes <- c(nframes, params$nframes - times[length(times)])
}
for (i in seq_along(states)) {
all_frames <- switch(type, point = tween_state(all_frames,
states[[i]], ease, nframes[i],
!!id, enter, exit),
path = transform_path(all_frames,
states[[i]], ease, nframes[i],
!!id, enter, exit, match),
polygon = transform_polygon(all_frames,
states[[i]], ease, nframes[i],
!!id, enter, exit, match),
sf = transform_sf(all_frames,
states[[i]], ease, nframes[i],
!!id, enter, exit),
stop(type,
" layers not currently supported by transition_time",
call. = FALSE))
}
true_frame <- seq(times[1], times[length(times)])
all_frames <- all_frames[
all_frames$.frame %in%
# which(true_frame > 0 & true_frame <= params$nframes),
true_frame[which(true_frame > 0 & true_frame <= params$nframes)], # tweak line A
,
drop = FALSE]
# all_frames$.frame <- all_frames$.frame - min(all_frames$.frame) + 1 # remove line B
all_frames$group <- paste0(all_frames$group, "<", all_frames$.frame, ">")
all_frames$.frame <- NULL
all_frames
})
transition_time2 <- function (time, range = NULL) {
time_quo <- enquo(time)
gganimate:::require_quo(time_quo, "time")
ggproto(NULL, TransitionTime2,
params = list(time_quo = time_quo, range = range))
}
结果:
Z %>%
ggplot(aes(x, y, group = interaction(p,s))) +
geom_point() +
facet_wrap(~s) +
transition_time2(t) +
ggtitle('{frame_time}')
定义全新的 ggproto 对象可能有点矫枉过正,坦率地说,我对 gganimate 包的了解还不够,无法确定这样做不会破坏其他任何东西。
作为一种破坏性较小的替代方案,我们可以简单地预处理数据框以包含每个方面的相同时间值范围(以及任何其他感兴趣的分组变量),并使新行不可见:
Z %>%
mutate(alpha = 1) %>%
tidyr::complete(t, s, p, fill = list(alpha = 0)) %>%
group_by(s, p) %>%
arrange(t) %>%
tidyr::fill(x, y, .direction = "up") %>%
ungroup() %>%
ggplot(aes(x, y, group = interaction(p, s), alpha = alpha)) +
geom_point() +
facet_wrap(~ s) +
scale_alpha_identity() +
transition_time(t) +
ggtitle('{frame_time}')
关于r - gganimate 和(有时)空方面的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55110492/
有没有办法将使用 ffmmeg_renderer 或 av_renderer 制作的电影保存为单独的文件?我总是将主题作为数据嵌入到 html 文件中。 最佳答案 使用来自@Roman 的示例,我将使
我有以下数据框: # Seed RNG set.seed(33550336) # Create data frame df 将显示一个整数。如果frame_time是一个常规变量,那么使用bquot
几天来我一直在努力解决这个问题,但我不明白我错过了什么。 gganimate 似乎没有在帧之间添加任何过渡。 我正在使用 Tour de France dataset from the tidytue
是否可以在一个动画循环后停止? 动画应执行到去年 2021 年,然后停止显示所有条形图! 这是一个使用 gganimate 的条形动画示例: library(tidyverse) library(gg
我想将我的数据的另一列值插入gganimate动画标题中。 例如,这里的状态级别变量是x,我想添加到标题变量y: df 1 1 a 2 2 a 3 3 b
我有以下生成静态图表的 R 脚本 library(ggplot2) library(dplyr) library(tidyr) library(stringr) library(gta
是否可以在 gganimate 循环之间添加暂停?我知道我们可以使用 interval 设置帧之间的间隔,但是有没有办法在循环回第一帧之前在最后一帧暂停? 将最终帧的多个副本插入到数据中的最佳方法是吗
我正在尝试使用 gganimate 绘制一段时间内 NHL 前 3 名得分手的图。目前,我有一个柱形图,其中 x 轴显示球员姓名,y 轴显示每个球员的进球数。这是我所拥有的静态版本: library(
我有一个如下所示的数据框: head(newnolarank) lon lat week b 1 -90.06445 29.97121 1 9 2 -90.06704 29.9
遵循源代码 Here 。我正在尝试用我的数据复制它。我有一个时间序列数据,我在 y 轴上绘制事件和非事件数字。这是我的示例数据结构: df <- tibble::tribble( ~Date, ~
我已经解析了电子游戏《反恐精英》中手榴弹 throw 的一些数据。下面的示例数据显示我有关于手榴弹从哪里 throw 、手榴弹爆炸的位置以及何时 throw 手榴弹的位置。 df % # Add
我正在尝试使用 gganimate 绘制一段时间内 NHL 前 3 名得分手的图。目前,我有一个柱形图,其中 x 轴显示球员姓名,y 轴显示每个球员的进球数。这是我所拥有的静态版本: library(
我第一次尝试 gganimate 包,但在处理缺失值 (NA) 时遇到了问题。如果我的问题很微不足道,但我找不到任何解决方案,我深表歉意。 这是我正在尝试做的事情的可重现示例: # Load libr
我正在使用 gganimate。假设我有这个 MWE: library(ggplot2) library(gganimate) ggplot(airquality, aes(Day, Temp)) +
使用 gganimate 从 ggplot 制作动画时,我需要设置较低的速度以允许人们读取数据。 阅读文档(很难找到选项)似乎“nframes”是正确的设置。但我不能减慢动画或设置持续时间。两种方法中
以下两行代码,取自 script ,做我认为他们应该做的;也就是使用之前生成的ggplot文件——gganim——在Rstudio的查看器(第一行)中创建一个动画,并将最后一个动画保存到我mac上的g
我正在尝试显示随着时间的推移构建的直方图。它将从 1952 年的数据开始,然后每年更新直方图,并不断增长。 路径似乎是 gganimate,我认为使用 transition_reveal随着时间的推移
我在设置动画时无法设置绘图的宽度。 因此,如果我使用库 gapminder 制作静态图,代码如下: library(ggplot2) library(gganimate) theme_set(them
我想将绘图标签(标题、副标题)对齐到图像的左侧,而不是绘图区域的左侧,以获得 gganimate 动画。 这可以通过转换为 gtable 然后修改布局来使用静态图表。动画需要一种不同的方法,因为 gg
试图创建一个具有简单特征的动画,本质上是一个区域分布图形式的空间变量的时间序列。 问题是多边形在动画播放时遍布整个情节。 这是一个可重现的示例,部分摘自 https://www.blog.cultur
我是一名优秀的程序员,十分优秀!