Нарисуйте несколько графиков на одном графике в R?

13

Используя следующий код, я попытался нарисовать четыре графика на графике R. Я не доволен этой цифрой, потому что между графиками много места, поэтому ширина графиков недостаточна для анализа графиков.

  1. Может ли кто-нибудь помочь мне создать хороший график с четырьмя графиками?

  2. Как сохранить метки оси X от 1 до 10 вместо стандартных 5?

Данные:

a1: 11,013 13,814 13,831 13,714 13,787 13,734 13,778 13,771 13,823 13,659

a2: 5,181 7,747 8,314 8,061 7,920 8,153 8,540 8,845 7,881 8,301

Я использовал данные a1 для b1, c1 и d1; a2 данные для b2, c2 и d2 только здесь.

Рисунок:

введите описание изображения здесь

Код:

        op=par(mfrow=c(4,1), mar=c(5.5,5.1,4.1,2.1))
        plot(a1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="A")
        lines(a2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
        par(xpd=T)
        legend(1,26.5,c("X","Y"),bty="n",horiz=T,cex=1.5,col=c("red1","darkblue"),text.col=c("red1","darkblue"),pch=c(1,3),lty=c(2,3),x.intersp=0.4,adj=0.2)
        plot(b1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="B")
        lines(b2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
        plot(c1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="C")
        lines(c2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
        plot(d1/1000, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="D")
        lines(d2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
   > mtext("Price", side=2, at=100,line=3,cex=1.1)
samarasa
источник
1
Не могли бы вы дать детали ваших данных? возможно, dput (data_from_r)
suncoolsu
@suncoolsu, я обновил вопрос с образцом данных. Спасибо.
Самараса
Что если бы у вас было 2 цвета и 4 типа линий на одной оси с легендой? Я хотел бы увидеть код и результаты для этого.
Пол
@ user87: 4 сюжета из 4 разных экспериментов. Поэтому я считаю, что лучше рисовать 4 графика, чтобы проанализировать результаты экспериментов.
Самараса
@ user87, я не уверен, что ты имеешь в виду. Возможно, если бы вы начали новый вопрос, кто-то ответил бы на него (я бы :))
Брэндон Бертельсен

Ответы:

16

Если вы хотите придерживаться чего-то похожего на метод, который вы использовали, то вы можете изучить команду layout (). Несколько других изменений деталей, и вы можете получить графики гораздо ближе друг к другу. Вы также можете поместить уникальные вещи, которые меняются между графиками в списке (например, данные и поля), а затем пройти через цикл. Также вы заметите, что я создал нижнюю ось с помощью команды direct axis (), чтобы вы могли контролировать, куда идут элементы.

layout(matrix(1:5, ncol = 1), widths = 1,
        heights = c(1,5,5,5,7), respect = FALSE)
par(mar=c(0, 4, 0, 0))
plot(1, type = 'n', axes = FALSE, bty = 'n', ylab = '')
legend('left', , c("X","Y"), bty="n", horiz=T, cex=1.5, col=c("red1","darkblue"), text.col=c("red1","darkblue"), pch=c(1,3), lty=c(2,3), x.intersp=0.4,adj=0.2)
par(mar=c(0, 4, 2, 1), bty = 'o')
plot(a1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", xaxt = 'n', cex.axis=1.4, cex.lab=1.3,cex=1.2, lwd=2.5, col="red1", lty=2, pch=1, main="A")
lines(a2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
par(xpd=T)
plot(b1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", xaxt = 'n', cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="B")
lines(b2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
plot(c1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", xaxt = 'n', cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="C")
lines(c2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
par(mar=c(4, 4, 2, 1))
plot(d1/1000, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", xaxt = 'n', cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="D")
lines(d2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
mtext("Price", side=2, at=40,line=2.5,cex=1.1)
axis(1, 1:10, cex.axis = 1.4)

сюжет

Я должен отметить, что я действительно не приложил усилий к тому, чтобы сделать это настолько хорошо, как мог, и вместо того, чтобы сделать этот первый фиктивный граф, я мог бы просто установить достаточно места в первом кадре. К сожалению, настройка mar () пытается заполнить фрейм, и верхнее поле влияет на расстояние, на котором находится метка над графиком, поэтому мне придется пойти и сделать все метки с помощью mtext () или text (), а не просто использовать основной настрой в пределах сюжета, и я не хотел делать это

Джон
источник
второй +1 для базовой графики. Я тщетно пытался написать что-то хорошее с помощью команды layout (). Я собираюсь вернуться сюда в следующий раз, когда мне нужно будет его использовать.
Крис Били
13

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

dat <- data.frame (x=rep (1:10, 8), y=c(a1, a2, b1, b2, c1, c2, d1, d2),
        var=factor (rep (c("X", "Y"), each=10)),
        graph=factor (rep (c("A", "B", "C", "D"), each=20)))

который дает:

    x           y var graph
1   1 0.556372979   X     A
2   2 0.754257646   X     A
3   3 0.815432905   X     A
4   4 0.559513013   X     A
5   5 0.763368168   X     A
6   6 0.426415259   X     A
7   7 0.597962532   X     A
8   8 0.723780143   X     A
9   9 0.228920116   X     A
10 10 0.607378894   X     A
11  1 0.865114425   Y     A
12  2 0.919804947   Y     A
13  3 0.437003794   Y     A
14  4 0.203349303   Y     A
15  5 0.620425977   Y     A
16  6 0.703170299   Y     A
17  7 0.174297656   Y     A
18  8 0.698144659   Y     A
19  9 0.732527016   Y     A
20 10 0.778057398   Y     A
21  1 0.355583032   X     B
22  2 0.015765144   X     B
23  3 0.315004753   X     B
24  4 0.257723585   X     B
25  5 0.506324279   X     B
26  6 0.028634427   X     B
27  7 0.475360443   X     B
28  8 0.577119754   X     B
29  9 0.709063777   X     B
30 10 0.308695235   X     B
31  1 0.852567748   Y     B
32  2 0.938889121   Y     B
33  3 0.080869739   Y     B
34  4 0.732318482   Y     B
35  5 0.325673156   Y     B
36  6 0.378161864   Y     B
37  7 0.830962248   Y     B
38  8 0.990504039   Y     B
39  9 0.331377188   Y     B
40 10 0.448251682   Y     B
41  1 0.967255983   X     C
42  2 0.722894624   X     C
43  3 0.039523960   X     C
44  4 0.003774719   X     C
45  5 0.218605160   X     C
46  6 0.722304874   X     C
47  7 0.576140686   X     C
48  8 0.108219812   X     C
49  9 0.258440127   X     C
50 10 0.739656846   X     C
51  1 0.528278201   Y     C
52  2 0.104415716   Y     C
53  3 0.966076056   Y     C
54  4 0.504415150   Y     C
55  5 0.655384900   Y     C
56  6 0.247340395   Y     C
57  7 0.193857228   Y     C
58  8 0.019133583   Y     C
59  9 0.799404908   Y     C
60 10 0.159209090   Y     C
61  1 0.422574508   X     D
62  2 0.823192614   X     D
63  3 0.808715876   X     D
64  4 0.770499188   X     D
65  5 0.049138399   X     D
66  6 0.747017767   X     D
67  7 0.239916970   X     D
68  8 0.152777362   X     D
69  9 0.052862276   X     D
70 10 0.937605577   X     D
71  1 0.850112019   Y     D
72  2 0.675407232   Y     D
73  3 0.273276166   Y     D
74  4 0.455995477   Y     D
75  5 0.695497498   Y     D
76  6 0.688414035   Y     D
77  7 0.454013633   Y     D
78  8 0.874853452   Y     D
79  9 0.568746031   Y     D

Затем используйте решетку xyplot:

library (lattice)
xyplot (y ~ x | graph, groups=var, data=dat, type="o",
        layout=c(1, 4), as.table=T, xlab="Time (secs)", ylab="Price")

который дает хороший график, как:

введите описание изображения здесь

РЕДАКТИРОВАТЬ:

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

my.text <- levels (dat$var)
my.lty <- c(2, 3)
my.pch <- c(1, 2)
my.col <- trellis.par.get ("superpose.symbol")$col[1:2]
xyplot (y ~ x | graph, groups=var, data=dat, type="o", pch=my.pch, lty=my.lty,
        main="Main Title", layout=c(1, 4), as.table=T, xlab="Time (secs)", ylab="Price",
        key=list (columns=2, text=list (my.text), points=list (pch=my.pch, col=my.col)))

введите описание изображения здесь

РЕДАКТИРОВАТЬ 2:

Вы можете упростить код и график, если две категории действительно такие простые, как «X» и «Y»:

xyplot (y ~ x | graph, groups=var, data=dat, type="o", pch=c("X", "Y"), cex=1.25, lty=c(2, 3),
        layout=c(1, 4), as.table=T, xlab="Time (secs)", ylab="Price")

который будет использовать «X» и «Y» в качестве символов точки. Вам вообще не нужна легенда, и вы можете выделить еще больше места для самих графиков. (С другой стороны, вам может не понравиться внешний вид, или вам будет сложнее определить точный центр точки, хотя это не такая большая проблема, как могло бы быть, поскольку линия проходит через каждую точку.)

РЕДАКТИРОВАТЬ 3:

На самом деле, вы должны добавить strip=F, strip.left=T,к графику, чтобы расположить метки A, B, C, D слева от графиков, что дает вам больше места на длинном графике, как это:

xyplot (y ~ x | graph, groups=var, data=dat, type="o", pch=my.pch, lty=my.lty,
        main="Main Title", layout=c(1, 4), as.table=T, xlab="Time (secs)", ylab="Price",
        strip.left=T, strip=F,
        key=list (columns=2, text=list (my.text), points=list (pch=my.pch, col=my.col),
        lines=list (lty=my.lty, col=my.col)))

введите описание изображения здесь

Wayne
источник
@Wayne: я пытаюсь сохранить легенду поверх графика, используя auto.key с аргументами space = "top", pch = c (1,2), lty = c (2,4), но значения pch и lty значения не работают. Более того, я бы хотел, чтобы в легенде X и Y были горизонтальными. Не могли бы вы помочь мне в этом.
Самараса
Да. Мне нужно использовать разные значения pch, чтобы различить X и Y на бумаге. Я могу использовать различные значения pch на графике, добавив аргумент pch (1,4) к xyplot, но он не отражается в легенде. Пожалуйста, дайте мне знать, как я могу использовать разные значения pch для X и Y в легенде.
Самараса
Хорошо, я понял это, как только приехал домой и сверился с книгой. Проверьте отредактированную версию.
Уэйн
Нет проблем. Я думаю, что мой EDIT 3 дает вам лучший график, который похож (но лучше выглядит и имеет больше графического пространства, чем) ваш оригинал. Я не сдвинул легенду, которая, на мой взгляд, довольно проста. Если вы хотите, чтобы линия проходила через точку в легенде, я думаю, что вам нужно перевести ее на следующий уровень сложности и сделать вещи draw.key, которые создают пользовательские гробы ( gridвещь: решетка и ggplot2 строятся на сетке) ,
Уэйн
Да, теперь график лучше. Однако было бы очень хорошо, если бы мы получили точку над линией в легенде, как мы получаем с помощью обычной функции сюжета.
Самараса
9

Вот версия решения @ Brandon, ggplot2которая включает в себя желаемое поведение легенды:

dat <- data.frame (x=rep (1:10, 8), y=runif(80),
        var=factor (rep (c("X", "Y"), each=10)),
        graph=factor (rep (c("A", "B", "C", "D"), each=20)))

ggplot(data = dat,aes(x = x, y = y)) + 
    facet_wrap(~graph,nrow = 4) + 
    geom_point(aes(shape = var)) + 
    geom_line(aes(colour = var, group = var)) + 
    labs(x = NULL, y = NULL, shape = "", colour = "") + 
    theme_bw() + 
    opts(legend.position = "top", legend.direction = "horizontal")

введите описание изображения здесь

Я считаю, что легенды гораздо проще ggplot2, но YMMV.

РЕДАКТИРОВАТЬ

Обращаясь к нескольким вопросам в комментариях. Чтобы указать конкретные типы точек или линий, вы должны использовать scale_aesthetic_manualгде aestheticлибо shape, linetypeи т. Д. Например:

ggplot(data = dat,aes(x = x, y = y)) + 
    facet_wrap(~graph,nrow = 4) + 
    geom_point(aes(shape = var)) + 
    geom_line(aes(colour = var, linetype = var, group = var)) + 
    labs(x = NULL, y = NULL, shape = "", colour = "", linetype = "") + 
    scale_shape_manual(values = 4:5) +
    theme_bw() + 
    opts(legend.position = "top", legend.direction = "horizontal")

Изменение размера меток различных осей выполняется путем изменения настроек в теме, обычно с использованием opts(). Например:

ggplot(data = dat,aes(x = x, y = y)) + 
    facet_wrap(~graph,nrow = 4) + 
    geom_point(aes(shape = var)) + 
    geom_line(aes(colour = var, linetype = var, group = var)) + 
    labs(x = "X Label", y = "Y Label", shape = "", colour = "", linetype = "") + 
    theme_bw() + 
    opts(legend.position = "top", legend.direction = "horizontal",
         axis.text.x = theme_text(size = 15),axis.title.y = theme_text(size = 25, angle = 90))

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

Joran
источник
2
Я часто предпочитаю ggplot2. На самом деле я быстро попробовал ggplot2, когда решетка становилась слишком сложной, и обнаружил, что не могу заставить легенду правильно отражать стили точек / линий, если я хочу явно выбирать формы и стили линий. Я, вероятно, сделал это неправильно, и он смог работать в графике, но обманул создание легенды ggplot. Не могли бы вы посмотреть, работает ли он для вас и опубликовать код?
Уэйн
@Joran: я пытался выяснить, чтобы изменить типы линий, типы точек и цвета, но безуспешно. Не могли бы вы сообщить нам, как мы можем изменить типы линий и т. Д. А также, пожалуйста, дайте нам знать, как мы можем увеличить размер x и y labs.
Самараса
Я сейчас на моем телефоне; если @Brandon не отредактирует свой ответ до того, как я вернусь домой с тем, что вы ищете, я вернусь к нему сегодня вечером.
Джоран
8

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

library(ggplot2) 

df <- data.frame(
parameter=runif(300),
Time=1:300,
split=sample(c(1:4),300,replace=T),
split2=sample(c(1:2),300,replace=T)
)

ggplot(df, aes(Time, parameter, colour=as.factor(split2))) + 
geom_line() + 
facet_wrap(~split,nrow=4)

Что дает нам диаграмму как:

введите описание изображения здесь

Брэндон Бертельсен
источник
1
Мне нравятся сетки в ggplot, но есть ли способ отключить светло-серый фон?
блюполь
1
+ opts(panel.background=theme_blank())
Брэндон Бертельсен
1
Если вы хотите внести другие изменения, вы можете напечатать, theme_get()чтобы увидеть, что вы можете изменить. Затем следуйте той же схеме, что и мой последний комментарий, устанавливая их=theme_blank()
Брэндон Бертельсен
2
Я собирался сделать ggplot2 сам, но подумал, что решетка будет более легким шагом. Любой из них обеспечивает структурированный способ построения графиков, подобных этому. Настраивать многие детали может быть сложно, но легко получить что-то привлекательное и читаемое. (Хотя вам действительно нужно обернуть голову, создавая правильный фрейм данных, из которого можно графически отобразить данные, вместо того, чтобы просто бросать что-то в график.
Уэйн
Я обнаружил, что Хэдли предоставил инструменты манипулирования данными в других своих пакетах для массирования данных в нужную форму. Если есть сомнения, ответ обычноmelt()
Брэндон Бертельсен