在同一个ggplot中绘制离散和连续尺度

问题描述 投票:0回答:4

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

我有一些 GIS 流数据,其中附加了一些分类属性,我可以绘制这些属性(下面代码中的

p1
)来获取: enter image description here

我还有一组具有连续响应的位置,我也可以绘制这些位置(下面代码中的

p2
)以获得: enter image description here 但是我无法将两者结合起来(下面代码中的
p3
)。我收到此错误

scales[[prev_aes]] 中的错误:尝试选择少于一个元素

注释掉行

scale_colour_hue("Strahler order") +
将错误更改为

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

基本上,ggplot2 似乎对

geom_path
调用和
geom_point
调用使用相同的尺度类型(连续或离散)。因此,当我将离散变量
factor(Strahler)
传递到
scale_colour_gradientn
尺度时,绘图失败。

有办法解决这个问题吗?如果尺度函数有一个

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)

干杯,

西蒙

r graphics ggplot2 gis
4个回答
13
投票

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

但是,我认为有些人可能希望了解如何实现这一目标。注意:我使用了此要点中的

代码使顶部图中的元素透明,这样它们就不会使下面的元素变得不透明:

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 ) )

请参阅我的答案

此处,了解如何将图例添加到网格布局上的另一个位置。

enter image description here


5
投票
问题并不像你想象的那么复杂。一般来说,您只能绘制一次美学图。所以调用

scale_colour_*

 两次对于 ggplot2 来说是没有意义的。它会试图将一个强行推向另一个。

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


3
投票
我目前没有时间提供完整的工作示例,但还有另一种方法值得在这里提及:

ggplot 中的 geom_point (scale_colour_manual) 中的填充和边框颜色

基本上,将 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 如何调用不同的美感(

color

fill


0
投票
使用 Elio Campitelli 的

ggnewscale

,现在可以更简单地在同一个 ggplot 中组合不同的色标(甚至离散和连续):

# OP data is no longer available, # example by Elio Campitelli from https://eliocamp.github.io/ggnewscale/, modified library(ggplot2) library(ggnewscale) # "melt(volcano)" topography <- data.frame(expand.grid(x = 1:nrow(volcano), y = 1:ncol(volcano)), z = as.vector(volcano)) # point measurements of something at a few locations set.seed(42) measurements <- data.frame(x = runif(30, 1, 80), y = runif(30, 1, 60), thing = sample(letters[1:5], 30, replace=TRUE) ) ggplot(mapping = aes(x, y)) + geom_contour(data = topography, aes(z = z, color = after_stat(level))) + # Color scale for topography scale_color_viridis_c(option = "D") + # geoms below will use another color scale new_scale_color() + geom_point(data = measurements, size = 3, aes(color = thing)) + # Color scale applied to geoms added after new_scale_color() scale_color_viridis_d(option = "A")

请记住,同一图中的多个色标

可能会造成混淆,并且有专用的软件包用于使用 ggplot 绘制地图(如 ggmapsf)。

© www.soinside.com 2019 - 2024. All rights reserved.