首页 文章

R:如何在ggplot2线图中重新排序图例键以匹配每个系列中的最终值?

提问于
浏览
5

我正在使用ggplot2绘制线图,显示多个仪器的价格随时间的变化 . 我成功地在图上获得了多行,并添加了显示最近价格变化的值 . 我想要做的(并且还没有实现)是重新排序图例键,以便最高涨的价格系列位于图例的顶部,然后是价格系列的关键,该价格序列的价格上涨第二,等等 .

在下图中,图例按字母顺序显示键 . 我想要做的是以DDD,AAA,CCC然后BBB的顺序显示图例关键条目,这是最近日期的性能顺序 . 我怎样才能做到这一点?

ggplo2 chart showing legend order

最小代码如下 .

require(ggplot2)
require(scales)
require(gridExtra)
require(lubridate)
require(reshape)

# create fake price data
set.seed(123)
monthsback <- 15
date <- as.Date(paste(year(now()), month(now()),"1", sep="-")) - months(monthsback)
mydf <- data.frame(mydate = seq(as.Date(date), by = "month", length.out = monthsback),
                      aaa = runif(monthsback, min = 600, max = 800),
                      bbb = runif(monthsback, min = 100, max = 200),
                      ccc = runif(monthsback, min = 1400, max = 2000),
                      ddd = runif(monthsback, min = 50, max = 120))

# function to calculate change
change_from_start <- function(x) {
   (x - x[1]) / x[1]
}

# for appropriate columns (i.e. not date), replace fake price data with change in price
mydf[, 2:5] <- lapply(mydf[, 2:5], function(myparam){change_from_start(myparam)})

# get most recent values and reshape
myvals <- mydf[mydf$mydate == mydf$mydate[nrow(mydf)],]
myvals <- melt(myvals, id = c('mydate'))

# plot multiple lines
p <- ggplot(data = mydf) +
    geom_line( aes(x = mydate, y = aaa, colour = "AAA"), size = 1) +
    geom_line( aes(x = mydate, y = bbb, colour = "BBB"), size = 1) +
    geom_line( aes(x = mydate, y = ccc, colour = "CCC"), size = 1) +
    geom_line( aes(x = mydate, y = ddd, colour = "DDD"), size = 1) +
    scale_colour_manual("", values = c("AAA" = "red", "BBB" = "black", "CCC" = "blue", "DDD" = "green")) +
    scale_y_continuous(label = percent_format()) +
    geom_text(data = myvals, aes(x = mydate + 30, y = value, label = sprintf("%+1.1f%%", myvals$value * 100)), size = 4, colour = "grey50") +
    opts(axis.title.y = theme_blank()) +
    opts()

# and output
print(p)

3 回答

  • 0

    试试这个:

    mydf <- melt(mydf,id.var = 1)
    mydf$variable <- factor(mydf$variable,levels = rev(myvals$variable[order(myvals$value)]),ordered = TRUE)
    
    # plot multiple lines
    p <- ggplot(data = mydf) +
        geom_line(aes(x = mydate,y = value,colour = variable,group = variable),size = 1) +
        scale_colour_manual("", values = c("aaa" = "red", "bbb" = "black", "ccc" = "blue", "ddd" = "green")) +
        scale_y_continuous(label = percent_format()) +
        geom_text(data = myvals, aes(x = mydate + 30, y = value, label = sprintf("%+1.1f%%", myvals$value * 100)), 
                    size = 4, colour = "grey50") +
        opts(axis.title.y = theme_blank()) +
        opts()
    
    # and output
    print(p)
    

    enter image description here

    我融化了您的完整数据集,为您节省了几行用于绘制代码 . 像往常一样,关键是要确保变量是有序因子 .

    要解决注释中出现的问题,只要您获得正确的顺序,就可以传递您希望在图例中显示的任何标签:

    ggplot(data = mydf) +
        geom_line(aes(x = mydate,y = value,colour = variable,group = variable),size = 1) +
        scale_colour_manual("", values = c("aaa" = "red", "bbb" = "black", "ccc" = "blue", "ddd" = "green"),labels = c('Company D','Company A','Company C','Company B')) +
        scale_y_continuous(label = percent_format()) +
        geom_text(data = myvals, aes(x = mydate + 30, y = value, label = sprintf("%+1.1f%%", myvals$value * 100)), 
                    size = 4, colour = "grey50") +
        opts(axis.title.y = theme_blank()) +
        opts()
    

    enter image description here

    Note :由于版本0.9.2 optsreplacedtheme ,例如:

    + theme(axis.title.y = element_blank())
    
  • 9

    我认为这是一种更简单的方法 . 融合数据框后,按日期值排序,并使用上次日期的值创建图例 . 由于您按值排序,因此图例将按顺序显示与您订购值的最大值相对应的行(最大值为分钟或最小值为最大值) . 代码如下 .

    require(ggplot2)
    require(scales)
    require(gridExtra)
    require(lubridate)
    require(reshape)
    
    # create fake price data
    set.seed(123)
    monthsback <- 15
    date <- as.Date(paste(year(now()), month(now()),"1", sep="-")) - months(monthsback)
    mydf <- data.frame(mydate = seq(as.Date(date), by = "month", length.out = monthsback),
                          aaa = runif(monthsback, min = 600, max = 800),
                          bbb = runif(monthsback, min = 100, max = 200),
                          ccc = runif(monthsback, min = 1400, max = 2000),
                          ddd = runif(monthsback, min = 50, max = 120))
    
    # function to calculate change
    change_from_start <- function(x) {
       (x - x[1]) / x[1]
    }
    
    # for appropriate columns (i.e. not date), replace fake price data with change in price
    mydf[, 2:5] <- lapply(mydf[, 2:5], function(myparam){change_from_start(myparam)})
    
    mydf <- melt(mydf, id.var=1)
    
    #Order by date and value.  Decreasing since want to order greatest to least
    mydf <- mydf[order(mydf$mydate, mydf$value, decreasing = TRUE),]
    
    #Create legend breaks and labels
    legend_length <- length(unique(mydf$variable))
    legend_breaks <- mydf$variable[1:legend_length]
    
    #Pass order through scale_colour_discrete
    ggplot(data=mydf) + geom_line(aes(x = mydate,y = value,colour = variable,group = variable),size = 1) + scale_colour_discrete(breaks=legend_breaks)
    
  • 0

    试试这个

    • 指南(color = guide_legend(reverse = T))

相关问题