Накресліть два графіки на одній графіці в R


570

Я хотів би побудувати y1 та y2 в одному сюжеті.

x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)
plot(x, y1, type = "l", col = "red")
plot(x, y2, type = "l", col = "green")

Але коли я роблю це так, вони не будуються в одному сюжеті разом.

У Matlab можна зробити hold on, але хтось знає, як це зробити в R?


3
Перевірте ?curve. Використовуйте add=TRUE.
ізоморфізми

Дивіться це запитання для отримання більш конкретних відповідей ggplot2.
Axeman

Відповіді:


617

lines()або points()додасть до наявного графіка, але не створить нове вікно. Тож вам потрібно було б зробити

plot(x,y1,type="l",col="red")
lines(x,y2,col="green")

10
Чому це не працює на наступному простому прикладі? > сюжет (гріх)> рядки (cos) Помилка в as.double (y): не можна примусити ввести тип "вбудований" у вектор типу "подвійний"
Френк

23
Це легко помітити. За допомогою сюжету (sin) ви передаєте функцію замість фактичних даних. plot () виявить це і, в свою чергу, використовувати plot.function () для побудови вашої функції (читайте на декількох відправленнях, щоб дізнатися більше про це). Однак строки.function () не визначені, тому рядки () не знають, що робити з параметром функції класу. рядки можуть мати справу лише з вашими даними та об'єктами часових рядів класу t.
Сумендра

27
@Frank зробити це таким чином : plot(sin); curve(cos, add=TRUE).
ізоморфізми

2
Як використовувати те саме, якщо x відрізняється? Скажімо, у мене є один x1 та y1 для одного графа, і додати ще один графік x2 та y2 в той же графік. І x1, і x2 мають однаковий діапазон, але різні значення.
Кавіпрія

1
lines(x2,y2,...)lines(x,y2,...)
Абсолютно

220

Ви також можете використовувати parта малювати на одному графіку, але різну вісь. Щось таке:

plot( x, y1, type="l", col="red" )
par(new=TRUE)
plot( x, y2, type="l", col="green" )

Якщо ви детально прочитаєте про parв R, ви зможете генерувати дійсно цікаві графіки. Ще одна книга, яку варто подивитися - це R Graphics Пола Мерреля.


3
Мій R видає мені помилку: Помилка в номіналі (fig (new = ІСТИНА)): не вдалося знайти функцію "fig"
Alessandro Jacopson

5
Чи зберігає ваш метод правильну шкалу (вісь y) для двох ділянок?
Алессандро Якопсон

1
@uvts_cvs Так, це зберігає початковий графік у тото.
Сем

10
Проблема в тому, що вона перепише кілька елементів сюжету. Я б включив xlab="", ylab="", ...і кілька інших у другу plot.
ізоморфізми

118

При побудові багатошарових сюжетів слід враховувати ggplotпакет. Ідея полягає у створенні графічного об’єкта з базовою естетикою та поступовому його посиленні.

ggplotстиль вимагає пакування даних data.frame.

# Data generation
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
df <- data.frame(x,y1,y2)

Основне рішення:

require(ggplot2)

ggplot(df, aes(x)) +                    # basic graphical object
  geom_line(aes(y=y1), colour="red") +  # first layer
  geom_line(aes(y=y2), colour="green")  # second layer

Тут + operatorвикористовується для додавання додаткових шарів до основного об'єкта.

З ggplotвами ви маєте доступ до графічного об’єкта на кожному етапі побудови графіку. Скажімо, звичайна покрокова настройка може виглядати так:

g <- ggplot(df, aes(x))
g <- g + geom_line(aes(y=y1), colour="red")
g <- g + geom_line(aes(y=y2), colour="green")
g

gстворює сюжет, і ви можете його бачити на кожному етапі (ну, після створення принаймні одного шару). Подальші зачарування сюжету також робляться створеним об’єктом. Наприклад, ми можемо додати мітки для осей:

g <- g + ylab("Y") + xlab("X")
g

Фінал gвиглядає так:

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

ОНОВЛЕННЯ (2013-11-08):

Як зазначається в коментарях, ggplotфілософія філософії пропонує використовувати дані у довгому форматі. Ви можете звернутися до цієї відповіді , щоб побачити відповідний код.


5
Як запропонував Генрік , дані дійсно повинні бути у форматі "довгий", ggplotобробляючи це природніше, ніж "широкий" формат, який ви використовуєте.
krlmlr

1
@Henrik: Ні, в першу чергу дякую за вашу відповідь. Можливо, автор цієї відповіді може відредагувати її так, щоб вона добре відповідала ggplotфілософії Росії ...
krlmlr

1
@krlmlr, я спробував відредагувати свою відповідь, щоб вона більш чітко вирішила питання. Не соромтеся запропонувати подальші оновлення. Ура.
Генрік

3
навчив мене визначати х на ggplot (aes ()), а потім y сам на geom _ * (). Приємно!
Dan

41

Я думаю, що відповідь, яку ви шукаєте:

plot(first thing to plot)
plot(second thing to plot,add=TRUE)

25
Це, здається, не працює, воно "add" is not a graphical parameterпопереджає, а потім друкує другий сюжет над першим.
Вальдір Леонсіо


Одним із приємних переваг цього є те, що, здається, зберігаються межі осей та заголовки. Деякі з попередніх методів змушують R намалювати два набори галочок на осі y, якщо у вас не виникне проблем із зазначенням додаткових варіантів. Потрібно сказати, що два набори галочок на осях можуть бути дуже оманливими.
RMurphy

1
Параметр add працює для деяких методів сюжету, але не базовий / за замовчуванням в R
cloudscomputes

2
Я отримав таку ж помилку "add" is not a graphical parameter. Мій R є R version 3.2.3 (2015-12-10). Ви можете використовувати par(new=TRUE)команду між цими графіками.
quepas

29

Використовуйте matplotфункцію:

matplot(x, cbind(y1,y2),type="l",col=c("red","green"),lty=c(1,1))

використовувати це, якщо y1і y2оцінюються в одних і тих же xпунктах. Він масштабує вісь Y, щоб відповідати тому, що більше ( y1або y2), на відміну від деяких інших відповідей тут, які будуть вирізати, y2якщо він стане більшим, ніжy1 (рішення ggplot з цим в основному добре).

Крім того, і якщо два рядки не мають однакових x-координат, встановіть межі осі на першому графіку та додайте:

x1  <- seq(-2, 2, 0.05)
x2  <- seq(-3, 3, 0.05)
y1 <- pnorm(x1)
y2 <- pnorm(x2,1,1)

plot(x1,y1,ylim=range(c(y1,y2)),xlim=range(c(x1,x2)), type="l",col="red")
lines(x2,y2,col="green")

Я здивований, цьому Q вже 4 роки, і ніхто не згадував matplotі x/ylim...


25

tl; dr: Ви хочете використовувати curveadd=TRUE) або lines.


Я не погоджуюся з par(new=TRUE)тим, що це вдвічі надрукує галочки та мітки осі. Напр

синус і парабола

Вихід plot(sin); par(new=T); plot( function(x) x**2 ).

Подивіться, як переплутані мітки вертикальної осі! Оскільки діапазони різні, вам потрібно буде встановити ylim=c(lowest point between the two functions, highest point between the two functions), що є менш простим, ніж те, що я збираюся показати вам ---, і набагато легше, якщо ви хочете додати не лише дві криві, а багато.


Те, що мене завжди плутало в плані, - це різниця між curveта lines. (Якщо ви не можете згадати, що це назви двох важливих графічних команд, просто заспівайте .)

Ось велика різниця між curveта lines.

curveбудуватиме функцію, як curve(sin). linesділянки з точки х і у значень, наприклад: lines( x=0:10, y=sin(0:10) ).

І ось незначна різниця: curveвам потрібно подзвонити add=TRUEза тим, що ви намагаєтесь зробити, тоді як linesуже передбачається, що ви додаєте до наявного сюжету.

id & sine

Ось результат дзвінка plot(0:2); curve(sin).


За лаштунками перевірте methods(plot). І перевірити body( plot.function )[[5]]. Коли ви називаєте plot(sin)R, то з'ясовується, що sinце функція (а не значення y) і використовується plot.functionметод, який завершує виклик curve. Так curveсамо інструмент призначений для обробки функцій.



16

Як описано в @redmode, ви можете побудувати дві лінії в одному графічному пристрої, використовуючи ggplot. У цій відповіді дані були у "широкому" форматі. Однак при їх використанні, ggplotяк правило, найзручніше зберігати дані у кадрі даних у "довгому" форматі. Потім, використовуючи різні "групування змінних" вaes групуючі аргументах тетики, властивості рядка, такі як лінійний тип або колір, будуть змінюватися залежно від змінної групування, і з’являться відповідні легенди.

У цьому випадку ми можемо використовувати colourестетику, яка відповідає кольорам ліній різним рівням змінної у наборі даних (тут: y1 проти y2). Але спершу нам потрібно плавити дані від широкого до довгого формату, використовуючи, наприклад, функцію 'melt' з reshape2пакету. Інші методи переформатування даних описані тут: Переформатування даних.кадр від широкого до довгого формату .

library(ggplot2)
library(reshape2)

# original data in a 'wide' format
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)
df <- data.frame(x, y1, y2)

# melt the data to a long format
df2 <- melt(data = df, id.vars = "x")

# plot, using the aesthetics argument 'colour'
ggplot(data = df2, aes(x = x, y = value, colour = variable)) + geom_line()

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


15

Якщо ви використовуєте базову графіку (тобто не грати / сітки), ви можете імітувати функцію MATLAB, утримуючи функцію, використовуючи функції точок / ліній / полігонів, щоб додати додаткові деталі до ваших ділянок, не починаючи новий графік. У випадку макета мультиплоту ви можете вибрати, par(mfg=...)до якого сюжету ви додасте речі.



7

Замість того, щоб зберігати значення, які плануються в масиві, зберігайте їх у матриці. За замовчуванням вся матриця буде розглядатися як один набір даних. Однак якщо ви додасте таку ж кількість модифікаторів до ділянки, наприклад, col (), як у вас є рядки в матриці, R визначить, що кожен рядок слід обробляти незалежно. Наприклад:

x = matrix( c(21,50,80,41), nrow=2 )
y = matrix( c(1,2,1,2), nrow=2 )
plot(x, y, col("red","blue")

Це має працювати, якщо ваші набори даних не мають різного розміру.


Це дає: Помилка if (as.factor) {: аргумент не трактується як логічний
baouss

5

Ідіоматичний Matlab plot(x1,y1,x2,y2)можна перекласти в R ggplot2за допомогою, наприклад, таким чином:

x1 <- seq(1,10,.2)
df1 <- data.frame(x=x1,y=log(x1),type="Log")
x2 <- seq(1,10)
df2 <- data.frame(x=x2,y=cumsum(1/x2),type="Harmonic")

df <- rbind(df1,df2)

library(ggplot2)
ggplot(df)+geom_line(aes(x,y,colour=type))

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

Натхненний двома лініями Tingting Zhao з різним діапазоном осі x за допомогою ggplot2 .


5

Ви можете використовувати ggplotly()функцію з пакету plotly, щоб перетворити будь-який із прикладів gggplot2 тут в інтерактивний сюжет, але я думаю, що такий тип сюжету краще без ggplot2 :

# call Plotly and enter username and key
library(plotly)
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)

plot_ly(x = x) %>%
  add_lines(y = y1, color = I("red"), name = "Red") %>%
  add_lines(y = y2, color = I("green"), name = "Green")

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


сюжетно виглядає блискуче; це безкоштовно?
деніс

@denis, існує необмежена кількість безкоштовних публічних сюжетів та приватних платних варіантів чи виплат. Див. Сторінку планів .
Матео Санчес

4
У пакеті R-пакет тепер на 100% безкоштовний та відкритий код (ліцензія MIT). Ви можете користуватися ним із сюжетом чи без нього.
Карсон

4

Ви також можете створити свою ділянку за допомогою ggvis :

library(ggvis)

x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
df <- data.frame(x, y1, y2)

df %>%
  ggvis(~x, ~y1, stroke := 'red') %>%
  layer_paths() %>%
  layer_paths(data = df, x = ~x, y = ~y2, stroke := 'blue')

Це створить наступний сюжет:

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


2

Використання plotly(додавання рішення plotlyз первинної та вторинної осі y; здається, його немає):

library(plotly)     
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)

df=cbind.data.frame(x,y1,y2)

  plot_ly(df) %>%
    add_trace(x=~x,y=~y1,name = 'Line 1',type = 'scatter',mode = 'lines+markers',connectgaps = TRUE) %>%
    add_trace(x=~x,y=~y2,name = 'Line 2',type = 'scatter',mode = 'lines+markers',connectgaps = TRUE,yaxis = "y2") %>%
    layout(title = 'Title',
       xaxis = list(title = "X-axis title"),
       yaxis2 = list(side = 'right', overlaying = "y", title = 'secondary y axis', showgrid = FALSE, zeroline = FALSE))

Скріншот робочої демонстрації:

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


Я скомпілював код і не працює, спершу позначив помилку в%>% і видалив її, потім позначив помилку, Error in library(plotly) : there is no package called ‘plotly’чому?
Bellatrix

Ви встановили пакет plotly? Вам потрібно встановити пакет за допомогою install.packages("plotly")команди.
Саурабх Чаухан

1

ми також можемо використовувати ґратчасту бібліотеку

library(lattice)
x <- seq(-2,2,0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
xyplot(y1 + y2 ~ x, ylab = "y1 and y2", type = "l", auto.key = list(points = FALSE,lines = TRUE))

Для конкретних кольорів

xyplot(y1 + y2 ~ x,ylab = "y1 and y2", type = "l", auto.key = list(points = F,lines = T), par.settings = list(superpose.line = list(col = c("red","green"))))

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.