【问题标题】:Plotting discrete and continuous scales in same ggplot在同一个ggplot中绘制离散和连续尺度
【发布时间】:2012-07-15 13:43:28
【问题描述】:

我想使用 ggplot2 绘制一些不同的数据项,使用两种不同的色标(一个连续的,一个来自两个不同 df 的离散)。我可以单独绘制我想要的任何一个,但我不能让它们一起工作。似乎您不能在同一个情节中使用两种不同的色标?我看到过类似的问题herehere,这让我相信我想要实现的目标在 ggplot2 中根本不可能,但以防万一我错了,我想说明我的问题如果有解决方法。

我有一些 GIS 流数据,其中附加了一些分类属性,我可以绘制(p1 在下面的代码中)来获得:

我还有一组具有连续响应的位置,我还可以绘制它们(下面的代码中的p2)来获得: 但是我不能将两者结合起来(下面代码中的p3)。我收到此错误

比例错误[[prev_aes]]:尝试选择少于一个元素

注释掉 scale_colour_hue("Strahler order") + 行会将错误更改为

错误:提供给连续刻度的离散值

基本上,ggplot2 似乎对geom_path 调用和geom_point 调用使用相同的比例类型(连续或离散)。因此,当我将离散变量 factor(Strahler) 传递给 scale_colour_gradientn 刻度时,绘图失败。

有没有办法解决这个问题?如果 scales 函数有一个 data 参数来告诉它应该从哪里映射或设置属性,那就太棒了。这甚至可能吗?

非常感谢下面的可重现代码:

library(ggplot2)

### Download df's   ###
oldwd <- getwd(); tmp <- tempdir(); setwd(tmp)
url <- "http://dl.dropbox.com/u/44829974/Data.zip"
f <- paste(tmp,"\\tmp.zip",sep="")
download.file(url,f)
unzip(f)


### Read in data    ###
riv_df <- read.table("riv_df.csv", sep=",",h=T)
afr_df <- read.table("afr_df.csv", sep=",",h=T)
vil_df <- read.table("vil_df.csv", sep=",",h=T)


### Min and max for plot area   ###
xmin <- -18; xmax <- 3; ymin <- 4; ymax <- 15


### Plot river data ###
p1 <-   ggplot(riv_df, aes(long, lat)) + 
    geom_map( mapping = aes( long , lat , map_id = id ) , fill = "white" , data = afr_df , map = afr_df ) +
    geom_path( colour = "grey95" , mapping = aes( long , lat , group = group , size = 1 ) , data = afr_df ) +
    geom_path( aes( group = id , alpha = I(Strahler/6) , colour = factor(Strahler) , size = Strahler/6 ) ) +
    scale_alpha( guide = "none" ) +
    scale_colour_hue("Strahler order") +
    scale_x_continuous( limits = c( xmin , xmax ) , expand = c( 0 , 0 ) ) +
    scale_y_continuous( limits = c( ymin , ymax ) , expand = c( 0 , 0 ) ) +
    coord_map()
print(p1) # This may take a little while depending on computer speed...



### Plot response data  ###
p2 <- ggplot( NULL ) +
    geom_point( aes( X , Y , colour = Z) , size = 2 , shape = 19 , data = vil_df ) +
    scale_colour_gradientn( colours = rev(heat.colors(25)) , guide="colourbar" ) +
    coord_equal()
print(p2)



### Plot both together  ###
p3 <-   ggplot(riv_df, aes(long, lat)) + 
    geom_map( mapping = aes( long , lat , map_id = id ) , fill = "white" , data = afr_df , map = afr_df ) +
    geom_path( colour = "grey95" , mapping = aes( long , lat , group = group , size = 1 ) , data = afr_df ) +
    geom_path( aes( group = id , alpha = I(Strahler/6) , colour = factor(Strahler) , size = Strahler/6 ) ) +
    scale_colour_hue("Strahler order") +
    scale_alpha( guide = "none" ) +
    scale_x_continuous( limits = c( xmin , xmax ) , expand = c( 0 , 0 ) ) +
    scale_y_continuous( limits = c( ymin , ymax ) , expand = c( 0 , 0 ) ) +
    geom_point( aes( X , Y , colour = Z) , size = 2 , shape = 19 , data = vil_df ) +
    scale_colour_gradientn( colours = rev(heat.colors(25)) , guide="colourbar" ) +
    coord_map()
print(p3)
#Error in scales[[prev_aes]] : attempt to select less than one element

### Clear-up downloaded files   ###
unlink(tmp,recursive=T)
setwd(oldwd)

干杯,

西蒙

【问题讨论】:

  • 问题并不像你想象的那么复杂。通常,您只能映射一次美学。所以两次调用scale_colour_*ggplot2 来说毫无意义。它会试图强迫一个进入另一个。
  • @joran 因此,目前没有办法将一种颜色美学从数据帧映射到连续比例,将另一种颜色美学从不同数据帧映射到离散比例?如果可以将数据指定为刻度,那会很方便,不是吗?
  • 在同一个图表中不能有多个色标,无论其中一个是连续的还是离散的。包作者说他们也不打算添加这个。实现起来相当复杂,并且很容易制作令人难以置信的混乱图表。 (由于类似的原因,永远不会实现多个 y 轴。)
  • @joran 感谢您的澄清。虽然我理解无法创建多个色阶(或其他美学)背后的谨慎,但如果有责任在内容创建者(和同行评审过程)上允许有意义和清晰的情节,我更愿意这样做,而不是故意受限于工具。但是,我很理解由于复杂性的原因没有实现这一点。 ggplot2 已经拥有如此广泛的功能集,我想这将很难集成。我绝对喜欢美学映射!
  • @joran 能否将您的 cmets 添加为答案,以便将此问题标记为已回答?

标签: r graphics ggplot2 gis


【解决方案1】:

你可以这样做。您需要告诉网格图形将一个图覆盖在另一个图之上。您必须获得边距和间距等,完全正确,并且您必须考虑顶层的透明度。简而言之……不值得。以及可能使情节混乱。

但是,我认为有些人可能会喜欢有关如何实现这一目标的指针。注:我使用code from this gist 使顶部图中的元素透明,这样它们就不会使下面的元素不透明:

grid.newpage()
pushViewport( viewport( layout = grid.layout( 1 , 1 , widths = unit( 1 , "npc" ) ) ) ) 
print( p1 + theme(legend.position="none") , vp = viewport( layout.pos.row = 1 , layout.pos.col = 1 ) )
print( p2 + theme(legend.position="none") , vp = viewport( layout.pos.row = 1 , layout.pos.col = 1 ) )

请参阅我的回答 here,了解如何将图例添加到网格布局的另一个位置。

【讨论】:

    【解决方案2】:

    问题并不像您想象的那么复杂。通常,您只能映射一次美学。所以调用scale_colour_* 两次对ggplot2 来说毫无意义。它会试图强迫一个进入另一个。

    您不能在同一个图表中拥有多个色标,无论其中一个是连续的还是离散的。包作者说他们也不打算添加这个。实现起来相当复杂,并且很容易制作令人难以置信的混乱图表。 (出于类似的原因,永远不会实现多个 y 轴。)

    【讨论】:

      【解决方案3】:

      我目前没有时间提供一个完整的工作示例,但这里值得一提的是另一种方法:Fill and border colour in geom_point (scale_colour_manual) in ggplot

      基本上,将 geom_point 与shape = 21, color = NA 结合使用可以让您使用fill 而不是color 美学来控制一系列点的颜色。这是我的代码的样子。我知道没有提供数据,但希望它可以为您提供一个起点:

      biloxi + 
        geom_point(data = filter(train, primary != 'na'), 
                   aes(y = GEO_LATITUDE, x = GEO_LONGITUDE, fill = primary), 
                   shape = 21, color = NA, size = 1) + 
          scale_fill_manual(values = c('dodgerblue', 'firebrick')) + 
        geom_point(data = test_map_frame, 
                   aes(y = GEO_LATITUDE, x = GEO_LONGITUDE, color = var_score), 
                  alpha = 1, size = 1) + 
          scale_color_gradient2(low = 'dodgerblue4', high = 'firebrick4', mid = 'white',
                          midpoint = mean(test_map_frame$var_score))   
      

      注意对 geom_point 的每次调用如何调用不同的审美(colorfill

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-04
        • 2018-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-04
        • 2015-04-22
        相关资源
        最近更新 更多