我正在努力研究一些东西,我相信,在R中应该是相当直接的。
请考虑以下示例:
library(dplyr)
library(tidyverse)
time = c('2013-01-03 22:04:21.549', '2013-01-03 22:04:22.349', '2013-01-03 22:04:23.559', '2013-01-03 22:04:25.559' )
value1 = c(1,2,3,4)
value2 = c(400,500,444,210)
data <- data_frame(time, value1, value2)
data <-data %>% mutate(time = as.POSIXct(time))
> data
# A tibble: 4 × 3
time value1 value2
<dttm> <dbl> <dbl>
1 2013-01-03 22:04:21 1 400
2 2013-01-03 22:04:22 2 500
3 2013-01-03 22:04:23 3 444
4 2013-01-03 22:04:25 4 210
我的问题很简单:
我想在SAME图表上用两个不同的Y轴绘制value1
AND value2
。
实际上,正如您在示例中所看到的,两个变量之间的单位差别很大,因此仅使用一个轴会压缩其中一个时间序列。
令人惊讶的是,为这个问题找到一张漂亮的图表已经证明是非常困难的。我很生气(当然,不是很生气。只是感到困惑;))。
在Python Pandas中,人们可以简单地使用:
data.set_index('time', inplace = True)
data[['value1', 'value2']].plot(secondary_y = 'value2')
在Stata中,人们可以简单地说:
twoway (line value1 time, sort ) (line value2 time, sort)
在R中,我不知道该怎么做。我在这里错过了什么吗? Base R,ggplot2
,一些奇怪的包,任何有正确定制选项的工作解决方案都可以。
答案 0 :(得分:1)
可以满足您需求的基础R hack。我会不遗余力地说明哪些组件(蓝色与红色)负责哪些组件。它很难看,但它展示了必要的要点。使用您的数据:
# making sure the left and right sides have the same space
par(mar = c(4,4,1,4) + 0.1)
# first plot
plot(value1 ~ time, data = data, pch = 16, col = "blue", las = 1,
col.axis = "blue", col.lab = "blue")
grid(lty = 1, col = "blue")
# "reset" the whole plot for an overlay
par(fig = c(0,1,0,1), new = TRUE)
# second plot, sans axes and other annotation
plot(value2 ~ time, data = data, pch = 16, col = "red",
axes = FALSE, ann = FALSE)
grid(lty = 3, col = "red")
# add the right-axis and label
axis(side = 4, las = 1, col.axis = "red")
mtext("value2", side = 4, line = 3, col = "red")
我添加了网格以突出美学问题:他们不能整齐地对齐#34;。如果您对此感到满意,请立即停止。
这是一种方法(尚未使用明显不同的数据范围进行测试)。 (根据您的数据和偏好,肯定有其他方法。)
# one way that may "normalize" the y-axes for you, so that the grid should be identical
y1 <- pretty(data$value1)
y1n <- length(y1)
y2 <- pretty(data$value2)
y2n <- length(y2)
if (y1n < y2n) {
y1 <- c(y1, y1[y1n] + diff(y1)[1])
} else if (y1n > y2n) {
y2 <- c(y2, y2[y2n] + diff(y2)[1])
}
随后的情节,添加ylim=range(...)
:
# making sure the left and right sides have the same space
par(mar = c(4,4,1,4) + 0.1)
# first plot
plot(value1 ~ time, data = data, pch = 16, col = "blue", las = 1, ylim = range(y1),
col.axis = "blue", col.lab = "blue")
grid(lty = 1, col = "blue")
# "reset" the whole plot for an overlay
par(fig = c(0,1,0,1), new = TRUE)
# second plot, sans axes and other annotation
plot(value2 ~ time, data = data, pch = 16, col = "red", ylim = range(y2),
axes = FALSE, ann = FALSE)
grid(lty = 3, col = "red")
# add the right-axis and label
axis(side = 4, las = 1, col.axis = "red")
mtext("value2", side = 4, line = 3, col = "red")
(虽然红蓝交替的网格线是残酷的,但它们表明网格确实很好地对齐。)
注意:使用par(fig = c(0,1,0,1), new = TRUE)
有点脆弱。做一些事情,比如改变图表之间的边距或其他重大变化,很容易打破叠加层,除非你做一些手工工作,看看添加过程实际上是如何实现的,否则你不会真正知道。在这&#34;检查&#34;过程中,您可能希望从第二个图中删除axes=F, ann=F
,以确认至少框和x轴按预期对齐。
答案 1 :(得分:1)
版本2.2.0 ggplot2
允许定义辅助轴。现在,第二个时间序列可以适当缩放并显示在同一个图表中:
data %>%
mutate(value2 = value2 / 100) %>% # scale value2
gather(variable, value, -time) %>% # reshape wide to long
ggplot(aes(time, value, colour = variable)) +
geom_point() + geom_line() +
scale_y_continuous(name = "value1", sec.axis = sec_axis(~ . * 100, name = "value2"))