2017-02-12 10 views
-2

я борюсь с чем-то, что, я считаю, должно быть довольно straighforward в R.Multiple внутридневные временных рядов на том же графике

Пожалуйста, рассмотрим следующий пример:

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 

Моя проблема проста:

Я хочу построить value1 И value2 на одинаковой карте с двумя разными Y-осями.

Действительно, как вы можете видеть в примере, единицы в значительной степени отличаются между двумя переменными, поэтому использование одной оси будет сжимать один из временных рядов.

Удивительно, но получить красивый график для этой проблемы оказалось очень сложно. Я сумасшедший (конечно, не совсем безумный, просто озадаченный;)).

В Python панд, можно было бы просто использовать:

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, какой-то странный пакет, любое рабочее решение с достойными настройками будет прекрасно.

+2

Hadley уже неоднократно говорил (и на этом сайте, если вы будете искать), что он думает, что двойные Y-оси вводят в заблуждение, если только они не просто конверсии (например, Celcius и Fahrenheit). Вместо этого используйте масштаб шкалы или грани, например. 'Библиотека (tidyverse); data%>% gather (var, val, -time)%>% ggplot (aes (time, val, color = var)) + geom_line() + scale_y_log10() ' – alistaire

+0

@alistaire это не дубликат, потому что здесь есть компонент datetime оси x, который отличается от многих примеров в SO. –

+0

@alistaire также, этот аргумент против двойной оси - чистая чепуха. Откройте любую эконометрическую книгу, содержащую временные ряды, и вы увидите повсюду графики с двумя осями. То, что двойная ось y вводит в заблуждение людей, абсурдна. Конечно, никто не считает, что линия, пересекающаяся в двухосевом графике, на самом деле пересекает эту точку. Это всего лишь артефакт диаграммы! Двойной осевой график связан с совместным движением. Во всяком случае, иначе ggplot2 - мой любимый ежедневный пакет, конечно. Здесь мне просто нужно что-то, что работает ... –

ответ

1

Базовый R-хак, который может ответить на ваши потребности. Я пропущу свой путь, чтобы понять, какие компоненты (синий или красный) отвечают за какие компоненты. Это уродливо, но это демонстрирует необходимые моменты. Использование данных:

# 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") 

misaligned grids

Я добавил сетки, чтобы выделить эстетическую проблему: они не совпадают «аккуратно». Если вы в порядке, не стесняйтесь сейчас.

Вот один из методов (который не был протестирован со значительно разными диапазонами данных). (Есть, безусловно, и другие методы в зависимости от ваших данных и ваших предпочтений.)

# 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") 

aligned grids

(Хотя красно-синего чередование линии сетки являются ужасными, они демонстрируют, что сетки действительно выравниваются хорошо.)

NB: использование par(fig = c(0,1,0,1), new = TRUE) немного хрупко. Выполнение таких вещей, как изменение полей или другие существенные изменения между сюжетами, может легко сломать оверлей, и вы не будете знать, если не выполните какую-либо ручную работу, чтобы увидеть, как процесс аддитивности фактически выполняется. В этом процессе проверки вы, скорее всего, захотите удалить axes=F, ann=F со второго участка, чтобы подтвердить, что по крайней мере поля и ось x выравниваются по назначению.

+0

изумительный !!! но человек эти диаграммы ужасны, спасибо, позвольте мне попробовать, что –

+1

Некоторые другие ссылки, которые могут быть полезны: http://rpubs.com/kohske/dual_axis_in_ggplot2 и http://stackoverflow.com/questions/21981416/dual-y-axis- в-ggplot2-для-множественной панель-фигура. – r2evans

+1

Одна из (многих) вещей, которые, по моему мнению, «ggplot2» преуспевают, - это следовать «грамматике графики», большая ее часть визуально интуитивно понятна. Увязывая оси y с очевидным различием точек/линий (т. Е. Цвета), я думаю, что он имеет тенденцию смягчать беспокойство по поводу смешения шкал. Хотя мой выбор палитр здесь оставляет желать лучшего, следует проявлять осторожность, чтобы вы поощряли очевидное различие. (Использование одного и того же цвета/точечного/линейного типа для всех точек данных может быть безответственным изображением, предполагая концепцию «хорошего управления сюжетом».) – r2evans

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")) 

enter image description here

+0

очень милый, но вот как-то вы обманываете, потому что вы определяете масштаб вручную. любую возможность сделать это автоматически? У меня много разных временных рядов ... –

+0

Я думаю, что это очень чисто, но вы видите способ автоматизировать перемасштабирование? –