- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我为特定一天的每个小时创建了风动画 ( Click to play animation video )。我不想显示 19 个点,而是想创建一个在整个区域每小时使用这 19 个点进行插值/外推的等高线图 - 就像使用 ArcGIS 和样条插值工具生成的等高线图一样。
以下代码显示了我用来创建每小时风动画的 ggplot 和 gganimate。我只创建了一个小数据框作为完整 24 小时数据的子样本,因为我不熟悉将 csv 附加到此论坛中。有没有办法包含覆盖该区域的轮廓而不是geom_point
?
library(ggplot2)
library(ggmap)
library(gganimate)
site <- c(1:18, 1:18)
date <- data.frame(date=c(rep(as.POSIXct("2018-06-07 00:00:00"),18),rep(as.POSIXct("2018-06-07 01:00:00"),18)))
long <- c(171.2496,171.1985, 171.2076, 171.2236,171.2165,171.2473,171.2448,171.2416,171.2243,171.2282,171.2344,171.2153,171.2532,171.2444,171.2443,171.2330,171.2356,171.2243)
lati <- c(-44.40450,-44.38520,-44.38530,-44.38750,-44.39195,-44.41436,-44.38798,-44.38934,-44.37958,-44.37836,-44.37336,-44.37909,-44.40801, -44.40472,-44.39558,-44.40971,-44.39577,-44.39780)
PM <- c(57,33,25,48,34,31,52,48,31,51,44,21,61,53,49,34,60,18,41,26,28,26,26,18,32,28,27,29,22,16,34,42,37,28,33,9)
ws <- c(0.8, 0.1, 0.4, 0.4, 0.2, 0.1, 0.4, 0.2, 0.3, 0.3, 0.2, 0.7, NaN, 0.4, 0.3, 0.4, 0.3, 0.3, 0.8, 0.2, 0.4, 0.4, 0.1, 0.5, 0.5, 0.2, 0.3, 0.3, 0.3, 0.4, NaN, 0.5, 0.5, 0.4, 0.3, 0.2)
wd <- c(243, 274, 227, 253, 199, 327, 257, 270, 209, 225, 230, 329, NaN, 219, 189, 272, 239, 237, 237, 273, 249, 261, 233, 306, 259, 273, 218, 242, 237, 348, NaN, 221, 198, 249, 236,252 )
PMwind <- cbind(site,date,long,lati,PM, ws, wd)
tmlat <- c(-44.425, -44.365)
tmlon <- c(171.175, 171.285)
tim <- get_map(location = c(lon = mean(tmlon), lat = mean(tmlat)),
zoom = 14,
maptype = "terrain")
ggmap(tim) +
geom_point(aes(x=long, y = lati, colour=PM), data=PMwind,
size=3,alpha = .8, position="dodge", na.rm = TRUE) +
geom_spoke(aes(x=long, y = lati, angle = ((270 - wd) %% 360) * pi / 180), data=PMwind,
radius = -PMwind$ws * .01, colour="yellow",
arrow = arrow(ends = "first", length = unit(0.2, "cm"))) +
transition_states(date, transition_length = 20, state_length = 60) +
labs(title = "{closest_state}") +
ease_aes('linear', interval = 0.1) +
scale_color_gradient(low = "green", high = "red")+
theme_minimal()+
theme(axis.text.x=element_blank(), axis.title.x=element_blank()) +
theme(axis.text.y=element_blank(), axis.title.y=element_blank()) +
shadow_wake(wake_length = 0.01)
最佳答案
这是可以做到的,但我想说,使用当前的工具,这远非那么简单。要从问题中的数据集转换为动画轮廓,我们需要解决以下障碍:
我们只有几个数据点,不规则地分布在给定区域。轮廓生成通常需要规则的点网格。
geom_contour
/stat_contour
不能很好地处理边缘处的开放轮廓。请参阅here GH 讨论当我们尝试使用填充多边形的轮廓线时会发生什么。
与轮廓相关的多边形不一定会随着时间的推移而持续存在:它们会出现、消失、 split 成多个较小的多边形、合并成更大的多边形等。这使得 gganimate 中的事情变得很困难,因为它需要知道哪些元素T 帧中的元素对应于 T+1 帧中的哪些元素,以便正确地对它们进行插值。
前两个障碍可以通过现有的解决方法来解决。第三个需要一些非正统的黑客攻击。
获取每个日期值的 PMwind 的经度/纬度/PM 值,并使用 akima 包中的 interp
将它们插入到常规网格中。外推设置为 TRUE 的双三次样条插值将为您提供 40 x 40 的规则网格(默认情况下,如果满足以下条件,请更改 nx/ny 参数值)您希望网格具有插值 PM 值的更粗/更细的点。
library(dplyr)
PMwind2 <- PMwind %>%
select(date, long, lati, PM) %>%
tidyr::nest(-date) %>%
mutate(data = purrr::map(data,
~ akima::interp(x = .$long, y = .$lati, z = .$PM,
linear = FALSE, # use spline interpolation
extrap = TRUE) %>%
akima::interp2xyz(data.frame = TRUE))) %>%
tidyr::unnest()
> str(PMwind2) # there are 2 x 40 x 40 observations, corresponding to 2 dates
'data.frame': 3200 obs. of 4 variables:
$ date: POSIXct, format: "2018-06-07" "2018-06-07" "2018-06-07" ...
$ x : num 171 171 171 171 171 ...
$ y : num -44.4 -44.4 -44.4 -44.4 -44.4 ...
$ z : num 31.8 31.4 31 30.6 30.3 ...
在这里,我使用了 metR package 中的 geom_contour_fill
,这是 GH 线程中讨论的修复之一。 (isoband 包方法看起来也很有趣,但它比较新,而且我还没有测试过。)
library(ggplot2)
library(metR)
# define scale breaks to make sure the scale would be consistent across animated frames
scale.breaks = scales::fullseq(range(PMwind2$z), size = 10)
# define annotation layer & appropriate coord limits for map (metR's contour polygons
# don't go nicely with alpha < 1 in animation, as the order of layers could change,
# but we can overlay the map as a semi-transparent annotation layer over the contour
# polygons, instead of having ggmap layer beneath semi-transparent contour polygons.)
map.annotation <- list(
annotation_raster(tim %>% unlist() %>%
alpha(0.4) %>% # change alpha setting for map here
matrix(nrow = dim(tim)[1],
byrow = TRUE),
xmin = attr(tim, "bb")$ll.lon,
xmax = attr(tim, "bb")$ur.lon,
ymin = attr(tim, "bb")$ll.lat,
ymax = attr(tim, "bb")$ur.lat),
coord_quickmap(xlim = c(attr(tim, "bb")$ll.lon, attr(tim, "bb")$ur.lon),
ylim = c(attr(tim, "bb")$ll.lat, attr(tim, "bb")$ur.lat),
expand = FALSE))
p.base <- ggplot(PMwind2, aes(x = x, y = y, z = z))
# check static version of plot to verify that the geom layer works as expected
p.base +
geom_contour_fill(breaks = scale.breaks) +
facet_wrap(~date) +
map.annotation +
scale_fill_gradient(low = "green", high = "red",
aesthetics = c("colour", "fill"),
limits = range(scale.breaks)) +
theme_minimal()
生成动画绘图的每一帧后(但在将其打印/绘制到图形设备之前),获取其数据,创建一个新绘图(我们实际想要的绘图),并发送 改为图形设备。我们可以通过将一些代码插入到 plot_frame
中来实现这一点,这是 ggproto 对象 gganimate:::Scene
中进行绘图的函数。
Scene2 <- ggproto(
"Scene2", gganimate:::Scene,
plot_frame = function(self, plot, i, newpage = is.null(vp), vp = NULL,
widths = NULL, heights = NULL, ...) {
plot <- self$get_frame(plot, i)
# for each frame, use the plot data interpolated by gganimate to create a new plot
new.plot <- ggplot(data = plot[["data"]][[1]],
aes(x = x, y = y, z = z)) +
geom_contour_fill(breaks = scale.breaks) +
ggtitle(plot[["plot"]][["labels"]][["title"]]) +
map.annotation +
scale_fill_gradient(low = "green", high = "red",
limits = range(scale.breaks)) +
theme_minimal()
plot <- ggplotGrob(new.plot)
# no change below
if (!is.null(widths)) plot$widths <- widths
if (!is.null(heights)) plot$heights <- heights
if (newpage) grid::grid.newpage()
grDevices::recordGraphics(
requireNamespace("gganimate", quietly = TRUE),
list(),
getNamespace("gganimate")
)
if (is.null(vp)) {
grid::grid.draw(plot)
} else {
if (is.character(vp)) seekViewport(vp)
else pushViewport(vp)
grid::grid.draw(plot)
upViewport()
}
invisible(NULL)
})
我们还需要定义一系列中间函数,以便动画使用这个 Scene2
而不是原来的 gganimate:::Scene
。我之前用同样的方法回答过另一个问题here ,并对这样做的利弊进行了一些讨论。
library(magrittr)
create_scene2 <- function(transition, view, shadow, ease, transmuters, nframes) {
if (is.null(nframes)) nframes <- 100
ggproto(NULL, Scene2, transition = transition,
view = view, shadow = shadow, ease = ease,
transmuters = transmuters, nframes = nframes)
}
ggplot_build2 <- gganimate:::ggplot_build.gganim
body(ggplot_build2) <- body(ggplot_build2) %>%
as.list() %>%
inset2(4,
quote(scene <- create_scene2(plot$transition, plot$view, plot$shadow,
plot$ease, plot$transmuters, plot$nframes))) %>%
as.call()
prerender2 <- gganimate:::prerender
body(prerender2) <- body(prerender2) %>%
as.list() %>%
inset2(3,
quote(ggplot_build2(plot))) %>%
as.call()
animate2 <- gganimate:::animate.gganim
body(animate2) <- body(animate2) %>%
as.list() %>%
inset2(7,
quote(plot <- prerender2(plot, nframes_total))) %>%
as.call()
最后,结果如下:
library(gganimate)
animate2(p.base +
geom_point(aes(color = z)) + # this layer will be replaced by geom_contour_fill in
# the final plot; it's here as the placeholder in
# order for gganimate to interpolate the relevant data
transition_time(date) +
ggtitle("{frame_time}"),
nframes = 30, fps = 10) # you can increase nframes for smoother transition
# (which would also be much bigger in file size)
关于r - 如何使用 gganimate 创建带有风动画的轮廓?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55583611/
我使用 sails 1.0 版。从 0.12 升级到 1.0 后,我收到类似 的错误 Error: Trying to create an association on a model that do
我正在处理 sails 的 v0.10 版本,我遇到了一个令人费解的问题。我与我正在构建的应用程序有关系,这是一个简单的测验应用程序。问题出现在我的模型和关联的结构上: 测验 -> 问题 -> 答案
我有以下型号: 评论.js module.exports = { attributes: { id : { type : 'integer',
我在弄清楚 sails 政策时遇到困难,我按照教程进行操作,但仍然无法使其工作。 在我的policies.js 文件中: module.exports.policies = { '*':true,
我正在尝试利用 moment.js 的优势来解析 sails 应用下的 jade 模板中的日期。我读过,为了在 View 服务器端使用 moment.js,我必须利用 locals 的概念。 因此根据
我从昨天开始就一直在尝试,但不知何故它不起作用。我不知道我哪里出了问题。 这是connections.js中的代码 module.exports.connections = { mysql:
我想将 .populate() 与 Sails js 和 MongoDB 一起使用,所以我做了这样的事情: 我正在使用最新版本的 Sails、MongoDB 和 Node。 我的模型看起来像: //
我创建了一个 sails js 应用程序。我想为我的应用程序添加单元测试。我正在使用以下方法进行单元测试。 http://sailsjs-documentation.readthedocs.org/e
我正在尝试为用户创建通知。 描述中的通知网址如下所示http://localhost:1337/invited/accept?referrer=msgIcon&id=this-notification
我目前正在学习 SailsJS,我是 Angular 的用户。我知道 Angular 可以毫无问题地与 SailsJs 一起工作(Sails 回来了,Angular 在前面)并且它在我的应用程序上成功
我在 sails js 工作。我想返回变量 sequence[0].NextValue;。但我不明白。 function AutoGenerate(tablename) { S
我试图从名为 fairCustomer 的表中选择所有记录,其中business_type_id 等于值数组。我使用 sailsjs 作为服务器,使用 mysql 作为数据库,在前端我使用带有 typ
我正在 sails.js 中进行文件上传。我刚刚将文件上传到我的本地路径。但问题是当我再次上传相同的文件时意味着它将覆盖现有文件。 var uploadFile= req.file('SourceFi
我尝试通过 Controller 中的 Article 模型访问 findOne(),但没有成功。 我有这个错误 > error: Sending 500 ("Server Error") resp
我正在尝试从函数中获取 count 值并希望存储在函数外部。 var count; client.count({ index: 'employee',
有区别吗 sails generate user? 和 sails generate api user? 如果有,我在使用第一个命令时出错,得到这个结果: error: No generator ca
我正在开发一个应用程序来验证 Facebook 用户的身份。我对 Sails 和 Passport 都很陌生,所以我决定关注这个存储库:https://github.com/stefanbuck/sa
我正在用 sails js 创建一个服务。我想在返回之前更新 totalCount 的值。但问题是当返回在 async.series 的回调中时,我在调用它时得到一个未定义的。我应该怎么做? var
假设我有一个名为 Twins 的模型: var model = module.exports = { attributes: { name: { ty
我正在尝试使用 Sails 在我的数据库中创建一个新客户。当我通过 URL 手动输入参数时,这就像您期望的那样工作,但是当我通过表单使用 POST 方法时,我收到 404 not found 错误,当
我是一名优秀的程序员,十分优秀!