- 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/
我正在从 Stata 迁移到 R(plm 包),以便进行面板模型计量经济学。在 Stata 中,面板模型(例如随机效应)通常报告组内、组间和整体 R 平方。 I have found plm 随机效应
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
我想要求用户输入整数值列表。用户可以输入单个值或一组多个值,如 1 2 3(spcae 或逗号分隔)然后使用输入的数据进行进一步计算。 我正在使用下面的代码 EXP <- as.integer(rea
当 R 使用分类变量执行回归时,它实际上是虚拟编码。也就是说,省略了一个级别作为基础或引用,并且回归公式包括所有其他级别的虚拟变量。但是,R 选择了哪一个作为引用,以及我如何影响这个选择? 具有四个级
这个问题基本上是我之前问过的问题的延伸:How to only print (adjusted) R-squared of regression model? 我想建立一个线性回归模型来预测具有 15
我在一台安装了多个软件包的 Linux 计算机上安装了 R。现在我正在另一台 Linux 计算机上设置 R。从他们的存储库安装 R 很容易,但我将不得不使用 安装许多包 install.package
我正在阅读 Hadley 的高级 R 编程,当它讨论字符的内存大小时,它说: R has a global string pool. This means that each unique strin
我们可以将 Shiny 代码写在两个单独的文件中,"ui.R"和 "server.R" , 或者我们可以将两个模块写入一个文件 "app.R"并调用函数shinyApp() 这两种方法中的任何一种在性
我正在使用 R 通过 RGP 包进行遗传编程。环境创造了解决问题的功能。我想将这些函数保存在它们自己的 .R 源文件中。我这辈子都想不通怎么办。我尝试过的一种方法是: bf_str = print(b
假设我创建了一个函数“function.r”,在编辑该函数后我必须通过 source('function.r') 重新加载到我的全局环境中。无论如何,每次我进行编辑时,我是否可以避免将其重新加载到我的
例如,test.R 是一个单行文件: $ cat test.R # print('Hello, world!') 我们可以通过Rscript test.R 或R CMD BATCH test.R 来
我知道我可以使用 Rmd 来构建包插图,但想知道是否可以更具体地使用 R Notebooks 来制作包插图。如果是这样,我需要将 R Notebooks 编写为包小插图有什么不同吗?我正在使用最新版本
我正在考虑使用 R 包的共享库进行 R 的站点安装。 多台计算机将访问该库,以便每个人共享相同的设置。 问题是我注意到有时您无法更新包,因为另一个 R 实例正在锁定库。我不能要求每个人都关闭它的 R
我知道如何从命令行启动 R 并执行表达式(例如, R -e 'print("hello")' )或从文件中获取输入(例如, R -f filename.r )。但是,在这两种情况下,R 都会运行文件中
我正在尝试使我当前的项目可重现,因此我正在创建一个主文档(最终是一个 .rmd 文件),用于调用和执行其他几个文档。这样我自己和其他调查员只需要打开和运行一个文件。 当前设置分为三层:主文件、2 个读
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 5年前关闭。 Improve this qu
我的 R 包中有以下描述文件 Package: blah Title: What the Package Does (one line, title case) Version: 0.0.0.9000
有没有办法更有效地编写以下语句?accel 是一个数据框。 accel[[2]]<- accel[[2]]-weighted.mean(accel[[2]]) accel[[3]]<- accel[[
例如,在尝试安装 R 包时 curl作为 usethis 的依赖项: * installing *source* package ‘curl’ ... ** package ‘curl’ succes
我想将一些软件作为一个包共享,但我的一些脚本似乎并不能很自然地作为函数运行。例如,考虑以下代码块,其中“raw.df”是一个包含离散和连续类型变量的数据框。函数“count.unique”和“squa
我是一名优秀的程序员,十分优秀!