Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R ggplot2两侧的相同刻度(非连续)_R_Ggplot2 - Fatal编程技术网

R ggplot2两侧的相同刻度(非连续)

R ggplot2两侧的相同刻度(非连续),r,ggplot2,R,Ggplot2,目标 使用ggplot2(最新版本)生成一个图形,在比例不连续的情况下,该图形在绘图的两侧复制x轴或y轴 最小重复次数 # Example data dat1 <- tibble::tibble(x = c(rep("a", 50), rep("b", 50)), y = runif(100)) # Standard scatterplot p1 <- ggplot2::ggplot(dat1) + ggplot2::geom

目标

使用
ggplot2
(最新版本)生成一个图形,在比例不连续的情况下,该图形在绘图的两侧复制x轴或y轴

最小重复次数

# Example data
dat1 <- tibble::tibble(x = c(rep("a", 50), rep("b", 50)), 
                       y = runif(100))

# Standard scatterplot
p1 <- ggplot2::ggplot(dat1) +
    ggplot2::geom_boxplot(ggplot2::aes(x = x, y = y))
但是,当比例不连续时,这不起作用,因为其他
比例*
函数没有
秒轴
参数(这很有意义)

编辑

为清楚起见,我希望复制x轴或y轴,其中刻度是任何东西,而不仅仅是离散的(因子变量)。为了简单起见,我在最小reprex中使用了一个离散变量


例如,在非连续比例为
datetime
time
格式的情况下会出现此问题。

选项1:这不是很优雅,但它使用
cowplot::align_plots
功能工作:

library(cowplot)
library(ggplot2)

dat1 <- tibble::tibble(x = c(rep("a", 50), rep("b", 50)), 
                       y = runif(100))
p <- ggplot2::ggplot(dat1) +
  ggplot2::geom_boxplot(ggplot2::aes(x = x, y = y))
p <- p + ggplot2::scale_y_continuous(sec.axis = ggplot2::sec_axis(~ .)) 
p1 <- p + scale_x_discrete(position = c( "bottom"))
p2 <- p + scale_x_discrete(position = c( "top"))
plots <- align_plots(p1, p2, align="hv")
ggdraw() + draw_grob(plots[[1]]) + draw_grob(plots[[2]])
库(cowplot)
图书馆(GG2)
dat1

你可以通过在两边贴上相同的标签来调整这个答案。至于“你可以把任何非连续的东西转换成一个因子,但那更不雅观!”从你上面的评论来看,这就是非连续轴,所以我不知道为什么这会成为你的问题

TL:DR使用
as.numeric(…)
进行分类美观,并使用
比例连续(…,秒轴(~,…)
从原始数据手动提供标签


编辑以更新: 我碰巧回头看了看这个帖子,发现它被要求提供日期和时间。这使得问题的措辞不正确:日期和时间是连续的,而不是离散的。离散尺度是影响因素。日期和时间是按连续比例排列的。在引擎盖下,它们只是“1970-01-01”以来的几天或几秒钟

如果试图传递
秒轴
参数,即使它是
重复轴
,缩放x_日期
确实会抛出错误。为了解决这个问题,您可以将日期/时间转换为一个数字,然后使用标签愚弄您的刻度。虽然这需要一些技巧,但并不太复杂

library(lubridate)
library(dplyr)

df <- data_frame(tm = ymd("2017-08-01") + 0:10,
                 y = cumsum(rnorm(length(tm)))) %>% 
  mutate(tm_num = as.numeric(tm)) 
当您根据
y
绘制
tm_num
时,它就像普通数字一样处理,您可以使用
scale_x_continuous(sec.axis=dup_axis(),…)
。然后你必须弄清楚你想要多少个断点以及如何标记它们

breaks=
是一个函数,它接受数据的限制,并计算美观的中断。首先,您要舍入限制,以确保获得整数(日期与非整数不匹配)。然后生成所需宽度的序列(天数(2))。您可以使用
weeks(1)
months(3)
或其他方法,查看
?lubridate::days
。在引擎盖下,
days(x)
生成秒数(每天86400秒,每周604800秒,等等),
as_date
将其转换为Unix时代以来的天数,
as.numeric
将其转换回整数

labels=
是一个函数,它获取我们刚刚生成的整数序列,并将它们转换回可显示的日期

这也适用于时间而不是日期。虽然日期是整数天,但时间是整数秒(对于datetimes,从Unix纪元开始,或者对于times,从午夜开始)

假设你有一些以分钟为单位的观察结果,而不是以天为单位

代码类似,但有一些调整:

df <- data_frame(tm = ymd_hms("2017-08-01 23:58:00") + 60*0:10,
           y = cumsum(rnorm(length(tm)))) %>% 
  mutate(tm_num = as.numeric(tm)) 
在这里,我更新了虚拟数据,从午夜前到午夜后的11分钟。在
breaks=
中,我对其进行了修改,以确保我获得了创建休息的整数分钟数,将
as_date
更改为
as_datetime
,并使用
minutes(2)
每两分钟休息一次。在
labels=
中,我添加了一个功能性的
戳记(…)(…)
,它创建了一个很好的显示格式

最后只是几次

df <- data_frame(tm = milliseconds(1234567 + 0:10),
           y = cumsum(rnorm(length(tm)))) %>% 
  mutate(tm_num = as.numeric(tm)) 

df
这里我们有一个观察,从t=20min34.567秒开始,每毫秒观察11小时。所以在
breaks=
中,我们不需要任何舍入,因为我们现在不需要整数。然后我们每隔
毫秒(2)
使用一次中断。然后,
标签=
需要格式化以接受十进制秒,“%OS3”表示秒位数为3位小数(最多可接受6位,请参见
?strtime


这一切值得吗?可能不会,除非你真的想要一个复制的时间轴。我可能会将此作为一个问题发布在
ggplot2
GitHub上,因为
dup\u axis
应该“只使用”日期时间。

Sweet,谢谢。我现在不回答这个问题,因为我想要一个更优雅的解决方案,如果可能的话:-)。关于选项2,请参阅我的编辑,指定我想要一个适用于任何非连续比例的解决方案,而不仅仅是因子。当然,您可以将任何非连续的内容转换为因子,但这更不雅观!:-)。回复:编辑后,您可以复制连续变量的x轴和y轴。你认为哪些不是离散因素的其他用途?这是仅有的两种刻度类型。可能重复的刻度请参阅额外编辑。在我的上下文中,我想复制的量表是
datetime
time
。我认为你应该清楚地回答你原来的问题,而不是不断地更改帖子。我碰巧在翻阅旧答案,看到了你的编辑,以使时间生效。我在回答时就是这么做的。
library(forcats)
dat1$num <- as.numeric(fct_recode(dat1$x, "1" = "a", "2" = "b"))

x11();ggplot2::ggplot(dat1, (aes(x = num, y = y, group = num))) +
  geom_boxplot()+
ggplot2::scale_y_continuous(sec.axis = ggplot2::sec_axis(~ .)) +
  scale_x_continuous(position = c("top"), breaks = c(1,2), labels = c("a", "b"), 
                     sec.axis = ggplot2::sec_axis(~ .,breaks = c(1,2), labels = c("a", "b")))
library(lubridate)
library(dplyr)

df <- data_frame(tm = ymd("2017-08-01") + 0:10,
                 y = cumsum(rnorm(length(tm)))) %>% 
  mutate(tm_num = as.numeric(tm)) 
df

# A tibble: 11 x 3
           tm          y tm_num
       <date>      <dbl>  <dbl>
 1 2017-08-01 -2.0948146  17379
 2 2017-08-02 -2.6020691  17380
 3 2017-08-03 -3.8940781  17381
 4 2017-08-04 -2.7807154  17382
 5 2017-08-05 -2.9451685  17383
 6 2017-08-06 -3.3355426  17384
 7 2017-08-07 -1.9664428  17385
 8 2017-08-08 -0.8501699  17386
 9 2017-08-09 -1.7481911  17387
10 2017-08-10 -1.3203246  17388
11 2017-08-11 -2.5487692  17389
df %>% 
  ggplot(aes(tm_num, y)) + geom_line() +
  scale_x_continuous(sec.axis = dup_axis(),
                     breaks = function(limits) {
                       seq(floor(limits[1]), ceiling(limits[2]), 
                           by = as.numeric(as_date(days(2))))
                       },
                     labels = function(breaks) {as_date(breaks)})
df <- data_frame(tm = ymd_hms("2017-08-01 23:58:00") + 60*0:10,
           y = cumsum(rnorm(length(tm)))) %>% 
  mutate(tm_num = as.numeric(tm)) 
df

# A tibble: 11 x 3
                    tm        y     tm_num
                <dttm>    <dbl>      <dbl>
 1 2017-08-01 23:58:00 1.375275 1501631880
 2 2017-08-01 23:59:00 2.373565 1501631940
 3 2017-08-02 00:00:00 3.650167 1501632000
 4 2017-08-02 00:01:00 2.578420 1501632060
 5 2017-08-02 00:02:00 5.155688 1501632120
 6 2017-08-02 00:03:00 4.022228 1501632180
 7 2017-08-02 00:04:00 4.776145 1501632240
 8 2017-08-02 00:05:00 4.917420 1501632300
 9 2017-08-02 00:06:00 4.513710 1501632360
10 2017-08-02 00:07:00 4.134294 1501632420
11 2017-08-02 00:08:00 3.142898 1501632480
df %>% 
  ggplot(aes(tm_num, y)) + geom_line() +
  scale_x_continuous(sec.axis = dup_axis(),
                     breaks = function(limits) {
                       seq(floor(limits[1] / 60) * 60, ceiling(limits[2] / 60) * 60, 
                           by = as.numeric(as_datetime(minutes(2))))
                       },
                     labels = function(breaks) {
                       stamp("Jan 1,\n0:00:00", orders = "md hms")(as_datetime(breaks))
                       })
df <- data_frame(tm = milliseconds(1234567 + 0:10),
           y = cumsum(rnorm(length(tm)))) %>% 
  mutate(tm_num = as.numeric(tm)) 

df
# A tibble: 11 x 3
             tm          y   tm_num
   <S4: Period>      <dbl>    <dbl>
 1    1234.567S  0.2136745 1234.567
 2    1234.568S -0.6376908 1234.568
 3    1234.569S -1.1080997 1234.569
 4     1234.57S -0.4219645 1234.570
 5    1234.571S -2.7579118 1234.571
 6    1234.572S -1.6626674 1234.572
 7    1234.573S -3.2298175 1234.573
 8    1234.574S -3.2078864 1234.574
 9    1234.575S -3.3982454 1234.575
10    1234.576S -2.1051759 1234.576
11    1234.577S -1.9163266 1234.577
df %>% 
  ggplot(aes(tm_num, y)) + geom_line() +
  scale_x_continuous(sec.axis = dup_axis(),
                     breaks = function(limits) {
                       seq(limits[1], limits[2], 
                           by = as.numeric(milliseconds(3)))
                       },
                     labels = function(breaks) {format((as_datetime(breaks)),
                                                       format = "%H:%M:%OS3")})