我正在尝试使用R的 gganimate 包来创建一组直方图的动画,其中动画的每个帧都显示图像的直方图。我有~400张图片,所以~400列。我的数据如下:
| bins.left | bins.right | hist1 | hist 2 | ... | hist n |
如您所见,我需要将每列视为每帧中直方图的Y值。换句话说,我的动画应该迭代列。
但是我在互联网上研究过的所有例子似乎都只考虑一列作为帧的标识符。例如在this example中:
mapping <- aes(x = gdpPercap, y = lifeExp,
size = pop, color = continent,
frame = year)
p <- ggplot(gapminder, mapping = mapping) +
geom_point() +
scale_x_log10()
属性' Year '被视为迭代器。这些数据如下所示:
country continent year lifeExp pop gdpPercap
<fctr> <fctr> <int> <dbl> <int> <dbl>
1 Afghanistan Asia 1952 28.801 8425333 779.4453
2 Afghanistan Asia 1957 30.332 9240934 820.8530
3 Afghanistan Asia 1962 31.997 10267083 853.1007
4 Afghanistan Asia 1967 34.020 11537966 836.1971
5 Afghanistan Asia 1972 36.088 13079460 739.9811
6 Afghanistan Asia 1977 38.438 14880372 786.1134
我不想修改我的数据以适应这种模式的原因是,如果我将所有直方图保存在一列中,我的数据框将非常冗长(长度= ~16000 * 400)并且很难处理。此外,以一种令人困惑的方式保持我的数据并不直观。我相信我的问题必须有一个简单的解决方案。任何建议都受到高度赞赏。
答案 0 :(得分:2)
正如@Marius所说,如果你的数据是长格式的,你可以使这个工作。下面我创建一些假数据,然后制作动画情节。
library(tidyverse)
theme_set(theme_classic())
library(gganimate)
这里有10列值的假数据,我们想要变成直方图。
set.seed(2)
dat = replicate(10, runif(100)) %>% as.data.frame
数据采用宽屏格式,因此我们首先使用gather
函数将其转换为长格式:
d = dat %>% gather(key, value)
在新的长格式中,key
列告诉我们数据最初来自哪个直方图列。我们将其用作frame
并运行geom_histogram
:
p = ggplot(d, aes(value, frame=key)) +
geom_histogram()
gganimate(p)
你可以看到这不是我们想要的。 ggplot
实际上从所有数据生成了一个直方图,动画只是连续显示每个堆栈中来自key
的每个值的部分。
我们需要一种方法来让ggplot创建单独的直方图并为它们设置动画。我们可以通过预先分箱数据并使用geom_rect
创建直方图条来实现这一点:
d = dat %>% gather(key, value) %>%
mutate(bins = cut(value, breaks=seq(0,1,0.1),
labels=seq(0,0.9,0.1) + 0.05, include.lowest=TRUE),
bins = as.numeric(as.character(bins))) %>%
group_by(key, bins) %>%
tally
p = ggplot(d, aes(xmin=bins - 0.048, xmax=bins + 0.048, ymin=0, ymax=n, frame=key)) +
geom_rect() +
scale_y_continuous(limits=c(0, max(d$n)))
gganimate(p)
在回复您的评论时,我认为您不能使用gganimate
广泛的数据。 gganimate
需要一个frame
列,需要长格式的数据。但是,gganimate
是animation
包的包装,您可以使用for循环和saveGIF
函数直接创建动画GIF文件:
library(animation)
saveGIF({
for (i in names(dat)) {
p = ggplot(dat, aes_string(i)) +
geom_histogram(breaks=seq(0,1,0.1))
print(p)
}
}, movie.name="test.gif")