การพล็อตตัวแปรสองตัวเป็นบรรทัดโดยใช้ ggplot2 บนกราฟเดียวกัน


305

เป็นคำถามที่ค่อนข้างใหม่ แต่บอกว่าฉันมีข้อมูลเช่นนี้:

test_data <-
  data.frame(
    var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
    var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
    date = seq(as.Date("2002-01-01"), by="1 month", length.out=100)
  )

ฉันจะพล็อตทั้งอนุกรมเวลาvar0และvar1กราฟเดียวกันdateโดยใช้แกน x ได้ggplot2อย่างไร? คะแนนโบนัสหากคุณทำvar0และvar1สีที่แตกต่างและสามารถรวมตำนาน!

ฉันแน่ใจว่ามันง่ายมาก แต่ฉันไม่สามารถหาตัวอย่างได้

คำตอบ:


373

สำหรับตัวแปรจำนวนน้อยคุณสามารถสร้างเนื้อเรื่องได้ด้วยตนเอง:

ggplot(test_data, aes(date)) + 
  geom_line(aes(y = var0, colour = "var0")) + 
  geom_line(aes(y = var1, colour = "var1"))

3
ตัวอย่างที่ดี แต่จะปรับแต่งสีของตัวเอง (เช่นสีดำและสีส้ม) ได้อย่างไรเพราะดูเหมือนว่าคุณกำลังใช้colour=เป็นชื่อตัวแปร
ดาร์วินพีซี

1
แม้colour='var_names'ตามที่ระบุไว้โดย hadley ทำงานได้ดี แต่ @DaveX - จะเฉพาะเจาะจงมากขึ้นหากต้องการเลือกสีที่เฉพาะเจาะจงมากกว่าฟังก์ชั่นสีที่เลือกโดยอัตโนมัติ
I_m_LeMarque

ฉันจะเพิ่มคำอธิบายได้อย่างไร
user1700890

361

วิธีการทั่วไปคือการแปลงข้อมูลให้เป็นรูปแบบยาว (ใช้melt()จากแพคเกจreshapeหรือreshape2) หรือgather()/ pivot_longer()จากtidyrแพคเกจ:

library("reshape2")
library("ggplot2")

test_data_long <- melt(test_data, id="date")  # convert to long format

ggplot(data=test_data_long,
       aes(x=date, y=value, colour=variable)) +
       geom_line()

เอาต์พุต ggplot2

ดูคำถามนี้เกี่ยวกับการปรับแต่งข้อมูลจากแบบกว้างเป็นยาว


8
คุณยังสามารถใช้gather()ฟังก์ชั่นของtidyrแพ็คเกจเพื่อละลายข้อมูล:gather(test_data, variable, value, -date)
janosdivenyi

33

คุณต้องการข้อมูลให้อยู่ในรูปแบบ "สูง" แทนที่จะเป็น "wide" สำหรับ ggplot2 "wide" หมายถึงการสังเกตการณ์ต่อแถวโดยแต่ละตัวแปรเป็นคอลัมน์ที่แตกต่างกัน (เหมือนตอนนี้) คุณต้องแปลงเป็นรูปแบบ "สูง" โดยที่คุณมีคอลัมน์ที่บอกชื่อของตัวแปรและคอลัมน์อื่นที่บอกค่าของตัวแปร กระบวนการส่งผ่านจากกว้างไปสูงมักเรียกว่า "การหลอมละลาย" คุณสามารถใช้tidyr::gatherละลาย data frame ของคุณ:

library(ggplot2)
library(tidyr)

test_data <-
  data.frame(
    var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
    var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
    date = seq(as.Date("2002-01-01"), by="1 month", length.out=100)
  )
test_data %>%
    gather(key,value, var0, var1) %>%
    ggplot(aes(x=date, y=value, colour=key)) +
    geom_line()

หลายซีรี่ส์ ggplot2

เพียงเพื่อให้ชัดเจนdataว่าggplotมีการบริโภคหลังจากท่อผ่านทางgatherลักษณะเช่นนี้:

date        key     value
2002-01-01  var0    100.00000
2002-02-01  var0    115.16388 
...
2007-11-01  var1    114.86302
2007-12-01  var1    119.30996

13

ใช้ข้อมูลของคุณ:

test_data <- data.frame(
var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
Dates = seq.Date(as.Date("2002-01-01"), by="1 month", length.out=100))

ฉันสร้างเวอร์ชันที่ซ้อนกันซึ่งเป็นสิ่งที่ggplot()ต้องการทำงานกับ:

stacked <- with(test_data,
                data.frame(value = c(var0, var1),
                           variable = factor(rep(c("Var0","Var1"),
                                                 each = NROW(test_data))),
                           Dates = rep(Dates, 2)))

ในกรณีนี้การผลิตstackedค่อนข้างง่ายเนื่องจากเราต้องทำการจัดการสองสามอย่าง แต่reshape()และreshapeและและreshape2อาจมีประโยชน์หากคุณมีชุดข้อมูลจริงที่ซับซ้อนกว่าเพื่อจัดการ

เมื่อข้อมูลอยู่ในรูปแบบสแต็กนี้จะต้องมีการggplot()เรียกง่ายๆเพื่อสร้างพล็อตที่คุณต้องการด้วยความพิเศษทั้งหมด (หนึ่งเหตุผลว่าทำไมแพคเกจการพล็อตระดับสูงเช่นlatticeและggplot2มีประโยชน์มาก):

require(ggplot2)
p <- ggplot(stacked, aes(Dates, value, colour = variable))
p + geom_line()

ฉันจะปล่อยให้คุณจัดระเบียบป้ายกำกับแกนชื่อตำนาน ฯลฯ

HTH


1
ฉันคิดว่าคุณมี parens ที่ใส่ผิดที่ในโค้ดของคุณ ฉันคิดว่านี่คือสิ่งที่คุณเป็นหลังจาก: ซ้อน <- กับ (test_data, data.frame (ค่า = c (var0, var1)), ตัวแปร = ปัจจัย (ตัวแทน (c ("Var0", "Var1"))), แต่ละ = NROW (test_data) วันที่ = ตัวแทน (วันที่ 2)) นอกจากนี้จุดประสงค์ของคอลัมน์ "แต่ละ" คืออะไร และนี่ไม่ใช่เพียงวิธีที่ซับซ้อนและมีประสิทธิภาพน้อยกว่าในการละลายข้อมูลตามที่แสดงโดย rcs หรือไม่ ฉันคิดว่าฉันสามารถจินตนาการได้ว่าตัวอย่างที่ละลายจะไม่ทำงาน แต่มันก็เกือบจะเป็นเครื่องมือที่เหมาะสมสำหรับงานนี้ถ้าฉันไม่มีอะไรหายไป?
Chase

1
@chase ขอโทษนั่นก็คือ Emacs ESS ทำให้เกิดการเยื้อง แต่ละข้อเป็นข้อโต้แย้งrep()ดังนั้นเราจึงได้รับ 3 cols stackedเท่านั้น ฉันจะแก้ไขโค้ดเพื่อให้การเยื้องชัดเจนยิ่งขึ้น
Gavin Simpson

1
@chase; ความคิดเห็นของคุณเกี่ยวกับmelt()ดีและฉันทราบว่าแพคเกจ reshape [2] จะเป็นประโยชน์ที่นี่ ฉันไม่ว่าคุ้นเคยกับ reshape2 และสำหรับเช่นการจัดการที่ง่ายที่จะทำมันด้วยมือมีความซับซ้อนกว่าการเรียกร้องให้มันเป็นความพยายามน้อยที่สุดเท่าที่ฉันไม่จำเป็นต้องอ่านวิธีการใช้งานmelt() melt()และ rcs แอบเข้ามาพร้อมกับคำตอบของเขาในขณะที่ฉันผลิตของฉัน; เมื่อฉันเริ่มการตอบกลับไม่มีคำตอบ มากกว่าหนึ่งวิธีในการสกินแมว - อย่างที่พวกเขาพูด! ;-)
Gavin Simpson

7

ฉันยังใหม่กับ R แต่พยายามที่จะเข้าใจว่า ggplot ทำงานอย่างไรฉันคิดว่าฉันมีวิธีอื่นในการทำเช่นนั้น ฉันเพิ่งแบ่งปันอาจไม่ใช่โซลูชันที่สมบูรณ์แบบ แต่เพื่อเพิ่มมุมมองที่แตกต่างกัน

ฉันรู้ว่า ggplot ทำเพื่อให้ทำงานกับดาต้าเฟรมได้ดีขึ้น แต่บางทีมันก็มีประโยชน์ที่จะรู้ว่าคุณสามารถพล็อตเวกเตอร์สองตัวได้โดยตรงโดยไม่ต้องใช้ดาต้าเฟรม

กำลังโหลดข้อมูล ความยาวเวกเตอร์วันที่ดั้งเดิมคือ 100 ในขณะที่ var0 และ var1 มีความยาว 50 ดังนั้นฉันจึงวางแผนข้อมูลที่มีอยู่เท่านั้น (50 วันแรก)

var0 <- 100 + c(0, cumsum(runif(49, -20, 20)))
var1 <- 150 + c(0, cumsum(runif(49, -10, 10)))
date <- seq(as.Date("2002-01-01"), by="1 month", length.out=50)    

พล็อต

ggplot() + geom_line(aes(x=date,y=var0),color='red') + 
           geom_line(aes(x=date,y=var1),color='blue') + 
           ylab('Values')+xlab('date')

ป้อนคำอธิบายรูปภาพที่นี่

อย่างไรก็ตามฉันไม่สามารถเพิ่มคำอธิบายภาพที่ถูกต้องโดยใช้รูปแบบนี้ ไม่มีใครรู้ได้อย่างไร


1
นี่เป็นการเพิ่มตำนาน ggplot() + geom_line(aes(x=date,y=var0, group=1, colour = 'red')) + geom_line(aes(x=date,y=var1, group = 2, colour = 'blue')) + ylab('Values')+xlab('date')
flurbius
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.