动画
散点图
数据Oilcoal包含了8个国家从1965年到2009年的煤炭与石油消耗量(百万吨),除了美国和中国的Marker.size为1,其他国家的为0.5
head(Oilcoal)
# Country Year Coal Oil Marker.size Oil_proportion
#1 US 1965 291.8264 548.933 1 0.6529014
#2 US 1966 306.0005 575.664 1 0.6529287
#3 US 1967 300.2215 595.761 1 0.6649248
#4 US 1968 310.7278 635.452 1 0.6715975
#5 US 1969 312.0096 667.791 1 0.6815581
#6 US 1970 309.0609 694.590 1 0.6920633
在plot_ly
里添加帧数frame,完成动画
library(plotly)
pal <- c("red", "blue", "darkgreen", "black",
"yellow", "purple", "pink", "orange")
Oilcoal %>%
plot_ly(
x = ~Coal, y = ~Oil,
size = ~Marker.size,
color = ~Country,
colors = pal,
frame = ~Year, # 帧数为年份
text = ~Country,
hoverinfo = "text",
type = 'scatter',
mode = 'markers'
)
Year = 1993
添加mode=line,去除frame,用线图表示路径
plot_ly(Oilcoal, x=~Coal, y=~Oil,
type = 'scatter', mode= "lines",
split =~Country, color = ~Country, colors = pal) %>%
layout(title = "Tracking path from 1965 to 2009")
柱状图
关于各国Oil在总资源消耗中的比例,画柱状图动画。由于plotly
中并没有柱状图动画,我们可以用以下方法“曲线救国”:
- 生成一个新的data.frame使得每个国家每年多一个观察量,设需显示的值为0
Oilcoal2 <- Oilcoal[rep(row.names(Oilcoal),2), ]
for (i in 361:720) {
Oilcoal2$Oil_proportion[i] <- 0
}
Oilcoal2 <- Oilcoal2[order(Oilcoal2$Year, Oilcoal2$Country),]
head(Oilcoal2)
# Country Year Coal Oil Marker.size Oil_proportion
#46 Brazil 1965 1.735 14.878 0.5 0.89556372
#46.1 Brazil 1965 1.735 14.878 0.5 0.00000000
#226 China 1965 165.633 10.960 1.0 0.06206362
#226.1 China 1965 165.633 10.960 1.0 0.00000000
#91 France 1965 45.055 53.887 0.5 0.54463221
#91.1 France 1965 45.055 53.887 0.5 0.00000000
- 各国每年都有两个值,0和实际值,用线图将所有的这两点连起来就好了【机智的不行】
p <- Oilcoal2 %>%
plot_ly(
x = ~Country, y = ~Oil_proportion,
size = ~Marker.size,
color = ~Country,
colors = pal,
frame = ~Year,
text = ~Country,
hoverinfo = "text",
type = 'scatter',
mode = "lines",
showlegend = F
)
p
Year = 1993
p %>% animation_opts(easing = "elastic", redraw = F)
添加动画效果elastic(弹性),动画会更加好玩(Q弹),但是这也是有缺点的,例如细微的变化会被直接忽略掉,过大的变化会更加夸张。由于静图长得都一样,就不放图了,大家自己试一试吧
Guided 2D-Tour
可能翻译为二维导览图吧。这是一个很“神奇”的图,相当于用一束光从不同角度将一个高维空间印在了纸上。为了方便显示,这里用印度,中国,巴西三国(维度为3)不同年份的Coal消耗量作点。以下代码是老师给的,有点长,但很长知识
数据处理
library(tourr)
library(plotly)
index <- as.character(Oilcoal$Country) %in% c("India","China","Brazil")
Oilcoal2 <- dcast(Oilcoal[index,], Year~Country, value.var = "Coal")
Oilcoal2 <- as.matrix(Oilcoal2)
rownames(Oilcoal2) <- Oilcoal2[,"Year"]
mat <- scale(Oilcoal2[,-1])
head(mat)
# Brazil China India
# 1965 -1.51 -1.055 -1.09
# 1966 -1.47 -1.013 -1.09
# 1967 -1.46 -1.168 -1.08
# 1968 -1.46 -1.053 -1.06
# 1969 -1.41 -1.022 -1.02
# 1970 -1.35 -0.967 -1.05
作图
#设置步进
tour<- new_tour(mat, guided_tour(cmass), NULL)
steps <- c(0, rep(1/25, 180))
stepz <- cumsum(steps)
Projs<-lapply(steps, function(step_size){
step <- tour(step_size)
if(is.null(step)) {
.GlobalEnv$tour<- new_tour(mat, guided_tour(cmass), NULL)
step <- tour(step_size)
}
step
})
# 对每一个观察量进行投影
tour_dat <- function(i) {
step <- Projs[[i]]
proj <- center(mat %*% step$proj)
data.frame(x = proj[,1], y = proj[,2], state = rownames(mat))
}
# 数据点赋值
tour_dats <- lapply(1:length(steps), tour_dat)
tour_datz <- Map(function(x, y) cbind(x, step = y), tour_dats, stepz)
tour_dat <- dplyr::bind_rows(tour_datz)
# 对每一个坐标轴进行投影
proj_dat <- function(i) {
step <- Projs[[i]]
data.frame(x = step$proj[,1], y = step$proj[,2], variable = colnames(mat))
}
# 坐标轴赋值
proj_dats <- lapply(1:length(steps), proj_dat)
proj_datz <- Map(function(x, y) cbind(x, step = y), proj_dats, stepz)
proj_dat <- dplyr::bind_rows(proj_datz)
# 变换的坐标
ax <- list(
title = "", showticklabels = FALSE,
zeroline = FALSE, showgrid = FALSE,
range = c(-1.1, 1.1)
)
# 设置滑块属性
options(digits = 3)
tour_dat <- highlight_key(tour_dat, ~state, group = "A")
# 作图
tour <- proj_dat %>%
plot_ly(x = ~x, y = ~y, frame = ~step) %>%
add_segments(xend = 0, yend = 0, color = I("gray80")) %>%
add_text(text = ~variable) %>%
add_markers(data = tour_dat, text = ~state,
ids = ~state, hoverinfo = "text") %>%
layout(xaxis = ax, yaxis = ax, showlegend = F)
tour
【说实话,虽然这个图很酷,无论是代码意义上,还是想法上,但真的很不好看呢,比如此图不是preattentive的】