Соответствие значениям двойной оси Y в R

Я знаю, что не рекомендуется отображать 2 отдельные оси Y на одном графике, и что это может сбивать с толку и вводить в заблуждение.

Есть ли способ сопоставить значения оси Y? Например, найти способ сместить данные правой оси Y на графике (?) Например, я хотел бы, чтобы 40 по левой оси Y соответствовало -1 по правой оси Y, потому что эти два значения соответствуют началу категорий условий засухи.

Образец:

structure(list(Time = structure(c(9862, 9893, 9921, 9952, 9982, 
10013, 10043, 10074, 10105, 10135, 10166, 10196, 10227, 10258, 
10286, 10317, 10347, 10378, 10408, 10439), class = "Date"), Year = c(1997, 
1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 
1998, 1998, 1998, 1998, 1998, 1998, 1998, 1998), VCI = c(48.7488482440362, 
51.8662335250972, 54.4212125411374, 61.7338808190779, 63.9870065731148, 
61.3375357670741, 62.6197335631611, 63.0950799644754, 61.6276947895731, 
61.1298324406371, 64.4422427513358, 60.3823204404222, 60.5883337239537, 
61.8918834440238, 59.1304135098709, 62.1668350554954, 61.9352586665065, 
55.75795384214, 50.3371363875305, 52.5748728440737), TCI = c(53.7071192239754, 
53.6178820221828, 57.7831310561669, 57.3996088686986, 49.8613200877384, 
54.9673093834738, 42.4962626269047, 33.542249807155, 36.9526033996693, 
46.0464770178552, 49.5240246297537, 49.6298842520857, 47.9889200846868, 
40.3862301499032, 36.8605803231892, 38.8799158911488, 39.0120455451407, 
45.9071510330717, 55.8730250709158, 60.4339176493461), SPEI = c(0.385767341805337, 
-0.240467091114443, 0.218601001011986, 0.392296211626228, -0.0041472667529566, 
0.36089672045203, -0.415596363086708, -0.694577131096395, -0.53422184521265, 
0.372791671097943, 0.0714646484375678, 0.100567550879492, 0.484279813014397, 
-0.478876226785371, -0.591222448288627, -0.473201395390211, -0.347352514594038, 
-0.432571106796894, -0.259775061906046, 0.114961224539346)), row.names = c(NA, 
20L), class = "data.frame")

Вот код:

## Plot first set of data and draw its axis
par(mar = c(5, 5, 4, 4))
#VCI index
plot(variables$Time, variables$VCI, pch=20, cex=.9, axes=FALSE, ylim=c(0,100), xlab = "", ylab = "", 
     type = "l",col = "Aquamarine3", main = "Temporal trend - drought indices, growing season")
axis(2, ylim=c(0,100),col = "black",las=1)  ## las=1 makes horizontal labels
mtext("VCI and TCI",side=2,line=2.5)
box()
abline(h = 40, col = "black", lty = "dotted", lwd= 2)


## Allow a second plot on the same graph
par(new=TRUE)

#TCI index
plot(variables$Time, variables$TCI, pch=21, cex = 1.2, axes=FALSE, ylim=c(0,100), xlab = "", ylab = "", 
     type = "l",col = "Chocolate2", main = "Temporal trend - drought indices, growing season")
axis(2, ylim=c(0,100),col = "grey",las=1)  ## las=1 makes horizontal labels
mtext("VCI and TCI",side=2,line=2.5)
box()


## Allow a second plot on the same graph
par(new=TRUE)

## Plot the second plot and put axis scale on right
plot(variables$Time, variables$SPEI, pch=15, cex=.4, xlab = "", ylab = "", ylim=c(-2.5,2.5), 
     axes=FALSE, type = "l", col = "darkorchid3")
abline(h = -1.5, col = "black", lty = "dashed", lwd= 2)

## a little farther out (line=4) to make room for labels
mtext("SPEI",side=4,line=2.5)
axis(4, ylim=c(-2.5, 2.5), col = "black",col.axis = "black",las=1)

par(new=TRUE)
## Draw the time axis
axis(1, spei.df$Time, format(spei.df$Time, "%Y"), 20)
mtext("Time",side=1,col = "black",line=2.5)  

## Add Legend
legend("topleft",legend=c("VCI","TCI", "SPEI"),
       text.col=c("black","black", "black"), lty=1, lwd=2, col=c("Aquamarine3","Chocolate2", "darkorchid3"))
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я не уверен, как вы делаете это в базе R, но вы можете выровнять вторую ось с помощью небольшой математики и проб и ошибок с помощью ggplot2

library(tidyverse)

dat |>
  mutate(SPEI = (SPEI+(25/15))*15)|>
  pivot_longer(VCI:SPEI) |>
  mutate(name = factor(name, levels = c("VCI", "TCI", "SPEI"))) |>
  ggplot(aes(Time, value, color = name))+
  geom_line()+
  geom_hline(linetype = "dotted", yintercept = 40)+ 
  geom_hline(linetype = "dashed", yintercept = 2.5)+
  scale_color_manual(values = c("Aquamarine3", "Chocolate2", "darkorchid3"))+
  scale_y_continuous(name = "VCI and TCI", 
                     breaks = seq(0, 100, by = 20),
                     limits = c(0, 100),
                     sec.axis = sec_axis(trans = ~(./15)-(25/15), name = "SPEI", 
                                         breaks = seq(-2,5, by = 1)))+
  ggtitle("Temporal trend - drought indices, growing season")+
  labs(color = "")+
  theme(panel.background = element_blank(),
        panel.border = element_rect(fill = NA, color = "black"),
        legend.key = element_blank(),
        legend.box.background = element_rect(fill = NA, color = "black"),
        legend.position = c(0.07,0.87),
        legend.title = element_blank())

ОБНОВЛЯТЬ отредактировано, чтобы сделать 40 = -1

library(tidyverse)

dat |>
  mutate(SPEI = ((SPEI+(55/15))*15))|>
  pivot_longer(VCI:SPEI) |>
  mutate(name = factor(name, levels = c("VCI", "TCI", "SPEI"))) |>
  ggplot(aes(Time, value, color = name))+
  geom_line()+
  geom_hline(linetype = "dotted", yintercept = 40)+ 
  geom_hline(linetype = "dashed", yintercept = 32.5)+
  scale_color_manual(values = c("Aquamarine3", "Chocolate2", "darkorchid3"))+
  scale_y_continuous(name = "VCI and TCI", 
                     breaks = seq(0, 100, by = 20),
                     limits = c(0, 100),
                     sec.axis = sec_axis(trans = ~(./15)-(55/15), name = "SPEI", 
                                         breaks = seq(-4,3, by = 1)))+
  ggtitle("Temporal trend - drought indices, growing season")+
  labs(color = "")+
  theme(panel.background = element_blank(),
        panel.border = element_rect(fill = NA, color = "black"),
        legend.key = element_blank(),
        legend.box.background = element_rect(fill = NA, color = "black"),
        legend.position = c(0.07,0.87),
        legend.title = element_blank())

Спасибо за попытку! однако я не вижу разницы между вашим графиком и моим :)

Myr TH 27.11.2022 08:50

Я думал, вы сказали, что хотели бы, чтобы 40 соответствовали 1? Это то, что график показывает выше

AndS. 27.11.2022 16:27

Нет, это минус 1.

Myr TH 27.11.2022 16:30

ладно, честная ошибка. Я отредактирую и сделаю -1

AndS. 27.11.2022 16:33

Я не понимаю, что вы сделали, но... Огромное спасибо :)

Myr TH 27.11.2022 20:20

Все, что я сделал, это изменил масштаб данных и оси, чтобы выровнять значения, которые вы хотели. Все остальное просто форматирование для ggplot2

AndS. 27.11.2022 20:28

Вопрос можно решить, вычислив максимальное значение одной из осей от другой по формуле линейной интерполяции, объяснение смотрите в Википедии.

Здесь я предпочитаю дать более компактный и общий ответ, который можно повторно использовать в подобных случаях. В приведенном ниже решении используются случайные данные и не используется маркировка для конкретной задачи.

Это работает следующим образом:

  1. Создайте несколько случайных данных с одной серией для x и двумя сериями ya и yb для y.
  2. Установите пределы оси Y для ya, минимум для yb и соответствующие значения для обеих осей, но не указывайте максимальное значение для второй оси.
  3. Рассчитайте максимум для yb.
  4. Дальше можно делать все как обычно.
## create a few random test data
set.seed(123)
x <- 1:10
ya <- runif (x, min = 20, max = 70)
yb <- runif (x, min = -1.5, max= 1)

## set limits for the two y axes, but omit yb_max
ya_min <- 0; ya_max <- 100; yb_min <- -3

## set value, where the two axes should match
ya_match <- 40; yb_match <- -1

## calculate yb_max using linear interpolation (here: extrapolation)
yb_max <- yb_min + (ya_max - ya_min) * (yb_match - yb_min) / (ya_match - ya_min)

## set graphical parameter to increase margin for right axis
par(mar=c(5, 4, 5, 5) + .1)

## plot data set "a" 
plot(x, ya, type = "l", col = "black", ylim = c(ya_min, ya_max))
abline(h = ya_match, col = "grey", lty = "dashed")

## add a second plot for data set "b", omitting axes and axis labels
par(new = TRUE)
plot(x, yb, type = "l", col = "red", ylim = c(yb_min, yb_max),
     axes = FALSE, xlab = "", ylab = "")

## add right axis and axis label
axis(4)
mtext("yb", side = 4, line = 3, col = "red")

plot with two matching y axes

Другие вопросы по теме