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

R:如何对ggplot2线图中的图例键重新排序,以匹配每个系列中的最终值?,r,ggplot2,R,Ggplot2,我使用ggplot2绘制了显示多个仪器价格随时间变化的折线图。我成功地在绘图上获得了多行,并添加了显示最近价格变化的值。我想做的(但尚未实现)是重新排列图例键,使上涨最多的价格序列位于图例顶部,然后是上涨第二最多的价格序列键,依此类推 在下图中,图例按字母顺序显示键。我希望它能够按照DDD、AAA、CCC和BBB的顺序显示图例键条目,这是截至最近日期的性能顺序。我该怎么做 下面是最小的ish代码 require(ggplot2) require(scales) require(gridExtr

我使用ggplot2绘制了显示多个仪器价格随时间变化的折线图。我成功地在绘图上获得了多行,并添加了显示最近价格变化的值。我想做的(但尚未实现)是重新排列图例键,使上涨最多的价格序列位于图例顶部,然后是上涨第二最多的价格序列键,依此类推

在下图中,图例按字母顺序显示键。我希望它能够按照DDD、AAA、CCC和BBB的顺序显示图例键条目,这是截至最近日期的性能顺序。我该怎么做

下面是最小的ish代码

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)
require(ggplot2)
需要(天平)
需要(额外)
要求(润滑)
需要(重塑)
#伪造价格数据
种子集(123)
monthsback试试这个:

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)

注意:自0.9.2版以来,
opts
一直是由
主题
,例如:

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

我认为有一个更简单的方法。融化数据框后,按日期值对其进行排序,并使用最后一个日期的值创建图例。由于您是按值排序的,因此图例将按照与您排序值的方式(从最大值到最小值或从最小值到最大值)相对应的顺序显示行。代码如下

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)
require(ggplot2)
需要(天平)
需要(额外)
要求(润滑)
需要(重塑)
#伪造价格数据
种子集(123)
monthsback试试这个

  • 导轨(颜色=导轨\图例(反面=T))

完美!请注意,
有序因子
是不必要的。级别的顺序很重要,但ggplot2不关心因子是否有序。很高兴知道,@kohske,谢谢!我想我过于偏执于其他人的代码决定他们自己的排序,如果因子没有排序。多亏了joran,我避免了主数据帧的融化,但这并没有真正的后果,正如你所指出的那样,保存了很多样板文件。我想可以使用列表分别定义
values=c(“aaa”=“red”)
部分,这样我就不必在每次更改要打印的项目时都深入代码的ggplot部分了。。。?还要感谢kohske的输入。@joran我后来才意识到这个解决方案并没有真正达到我想要的效果,因为尽管变量(aaa、bbb等)是按值排序的,并且在图例键中显示为排序的,但图例键(aaa、bbb等)中的标签在上面的答案中没有使用。在最初的问题中,我没有明确表示希望在图例键中使用这些标签,而不是列名。我该怎么做?@SlowLearner只需将列名从aaa、bbb等更改为aaa、bbb等。
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)