Creates a tmap-element
that draws symbols, including symbols and dots. The color, size, and shape of the symbols can be mapped to data variables.
Usage
tm_symbols(
size = 1,
col = NA,
shape = 21,
alpha = NA,
border.col = NA,
border.lwd = 1,
border.alpha = NA,
scale = 1,
perceptual = FALSE,
clustering = FALSE,
size.max = NA,
size.lim = NA,
sizes.legend = NULL,
sizes.legend.labels = NULL,
n = 5,
style = ifelse(is.null(breaks), "pretty", "fixed"),
style.args = list(),
as.count = NA,
breaks = NULL,
interval.closure = "left",
palette = NULL,
labels = NULL,
drop.levels = FALSE,
midpoint = NULL,
stretch.palette = TRUE,
contrast = NA,
colorNA = NA,
textNA = "Missing",
showNA = NA,
colorNULL = NA,
shapes = 21:25,
shapes.legend = NULL,
shapes.legend.fill = NA,
shapes.labels = NULL,
shapes.drop.levels = FALSE,
shapeNA = 4,
shape.textNA = "Missing",
shape.showNA = NA,
shapes.n = 5,
shapes.style = ifelse(is.null(shapes.breaks), "pretty", "fixed"),
shapes.style.args = list(),
shapes.as.count = NA,
shapes.breaks = NULL,
shapes.interval.closure = "left",
legend.max.symbol.size = 0.8,
just = NA,
jitter = 0,
xmod = 0,
ymod = 0,
icon.scale = 3,
grob.dim = c(width = 48, height = 48, render.width = 256, render.height = 256),
title.size = NA,
title.col = NA,
title.shape = NA,
legend.size.show = TRUE,
legend.col.show = TRUE,
legend.shape.show = TRUE,
legend.format = list(),
legend.size.is.portrait = FALSE,
legend.col.is.portrait = TRUE,
legend.shape.is.portrait = TRUE,
legend.size.reverse = FALSE,
legend.col.reverse = FALSE,
legend.shape.reverse = FALSE,
legend.hist = FALSE,
legend.hist.title = NA,
legend.size.z = NA,
legend.col.z = NA,
legend.shape.z = NA,
legend.hist.z = NA,
id = NA,
interactive = TRUE,
popup.vars = NA,
popup.format = list(),
zindex = NA,
group = NA,
auto.palette.mapping = NULL,
max.categories = NULL
)
tm_squares(size = 1, col = NA, shape = 22, scale = 4/3, ...)
tm_bubbles(
size = 1,
col = NA,
shape = 21,
scale = 4/3,
legend.max.symbol.size = 1,
...
)
tm_dots(
col = NA,
size = 0.02,
shape = 19,
title = NA,
legend.show = TRUE,
legend.is.portrait = TRUE,
legend.z = NA,
...
)
tm_markers(
shape = marker_icon(),
col = NA,
border.col = NULL,
clustering = TRUE,
text = NULL,
text.just = "top",
markers.on.top.of.text = TRUE,
group = NA,
...
)
Arguments
- size
a single value or a
shp
data variable that determines the symbol sizes. The reference valuesize=1
corresponds to the area of symbols that have the same height as one line of text. If a data variable (which should be numeric) is provided, the symbol area sizes are scaled proportionally (or perceptually, seeperceptual
) where by default the symbol with the largest data value will getsize=1
(see alsosize.max
). If multiple values are specified, small multiples are drawn (see details).- col
color(s) of the symbol. Either a color (vector), or categorical variable name(s). If multiple values are specified, small multiples are drawn (see details).
- shape
shape(s) of the symbol. Either direct shape specification(s) or a data variable name(s) that is mapped to the symbols specified by the
shapes
argument. Note that the default shapes (specified byshapes
) is not supported in"view"
mode. See details for the shape specification.- alpha
transparency number between 0 (totally transparent) and 1 (not transparent). By default, the alpha value of the
col
is used (normally 1).- border.col
color of the symbol borders.
- border.lwd
line width of the symbol borders. If
NA
, no symbol borders are drawn.- border.alpha
transparency number, regarding the symbol borders, between 0 (totally transparent) and 1 (not transparent). By default, the alpha value of the
col
is used (normally 1).- scale
symbol size multiplier number.
- perceptual
by default (with
perceptual = FALSE
), the symbol area sizes are scaled proportionally to the data variables. This is done by taking the square root of the (normalized) data variable, since the plotting system (grid
package) expects size in radius rather than area. However, the perceived area of larger symbols is often underestimated. Flannery (1971) experimentally derived a method to compensate this for symbols, which is enabled by this argument; ifperceptual = TRUE
, not the suqare root (power exponent 0.5) is taken, but power exponent 0.5716.- clustering
value that determines whether the symbols are clustered in
"view"
mode. It does not work proportional bubbles (i.e.tm_bubbles
). One of:TRUE
,FALSE
, or the output ofmarkerClusterOptions
.- size.max
value that is mapped to
size=1
. By default (NA
), the maximum data value is chosen. Only applicable whensize
is the name of a numeric variable ofshp
- size.lim
vector of two limit values of the
size
variable. Only symbols are drawn whose value is greater than or equal to the first value. Symbols whose values exceed the second value are drawn at the size of the second value. Only applicable whensize
is the name of a numeric variable ofshp
- sizes.legend
vector of symbol sizes that are shown in the legend. By default, this is determined automatically.
- sizes.legend.labels
vector of labels for that correspond to
sizes.legend
.- n
preferred number of color scale classes. Only applicable when
col
is a numeric variable name.- style
method to process the color scale when
col
is a numeric variable. Discrete gradient options are"cat"
,"fixed"
,"sd"
,"equal"
,"pretty"
,"quantile"
,"kmeans"
,"hclust"
,"bclust"
,"fisher"
,"jenks"
,"dpih"
,"headtails"
, and"log10_pretty"
. A numeric variable is processed as a categorical variable when using"cat"
, i.e. each unique value will correspond to a distinct category. For the other discrete gradient options (except"log10_pretty"
), see the details inclassIntervals
(extra arguments can be passed on viastyle.args
). Continuous gradient options are"cont"
,"order"
, and"log10"
. The first maps the values ofcol
to a smooth gradient, the second maps the order of values ofcol
to a smooth gradient, and the third uses a logarithmic transformation. The numeric variable can be either regarded as a continuous variable or a count (integer) variable. Seeas.count
.- style.args
arguments passed on to
classIntervals
, the function that determine color classes (see alsostyle
).- as.count
when
col
is a numeric variable, should it be processed as a count variable? For instance, ifstyle = "pretty"
,n = 2
, and the value range of the variable is 0 to 10, then the column classes foras.count = TRUE
are 0; 1 to 5; 6 to 10 (note that 0 is regarded as an own category) whereas foras.count = FALSE
they are 0 to 5; 5 to 10. Only applicable ifstyle
is"pretty"
,"fixed"
, or"log10_pretty"
. By default,TRUE
ifstyle
is one of these, and the variable is an integer.- breaks
in case
style=="fixed"
, breaks should be specified. Thebreaks
argument can also be used whenstyle="cont"
. In that case, the breaks are mapped evenly to the sequential or diverging color palette.- interval.closure
value that determines whether where the intervals are closed:
"left"
or"right"
. Only applicable ifcol
is a numeric variable. Ifas.count = TRUE
,inverval.closure
is always set to"left"
.- palette
a palette name or a vector of colors. See
tmaptools::palette_explorer()
for the named palettes. Use a"-"
as prefix to reverse the palette. The default palette is taken fromtm_layout
's argumentaes.palette
, which typically depends on the style. The type of palette fromaes.palette
is automatically determined, but can be overwritten: use"seq"
for sequential,"div"
for diverging, and"cat"
for categorical.- labels
labels of the classes
- drop.levels
should unused classes be omitted?
FALSE
by default.- midpoint
The value mapped to the middle color of a diverging palette. By default it is set to 0 if negative and positive values are present. In that case, the two sides of the color palette are assigned to negative respectively positive values. If all values are positive or all values are negative, then the midpoint is set to
NA
, which means that the value that corresponds to the middle color class (seestyle
) is mapped to the middle color. Only applies whencol
is a numeric variable. If it is specified for sequential color palettes (e.g."Blues"
), then this color palette will be treated as a diverging color palette.- stretch.palette
Logical that determines whether the categorical color palette should be stretched if there are more categories than colors. If
TRUE
(default), interpolated colors are used (like a rainbow). IfFALSE
, the palette is repeated.- contrast
vector of two numbers that determine the range that is used for sequential and diverging palettes (applicable when
auto.palette.mapping=TRUE
). Both numbers should be between 0 and 1. The first number determines where the palette begins, and the second number where it ends. For sequential palettes, 0 means the brightest color, and 1 the darkest color. For diverging palettes, 0 means the middle color, and 1 both extremes. If only one number is provided, this number is interpreted as the endpoint (with 0 taken as the start).- colorNA
colour for missing values. Use
NULL
for transparency.- textNA
text used for missing values of the color variable.
- showNA
logical that determines whether missing values are named in the legend. By default (
NA
), this depends on the presence of missing values.- colorNULL
colour for polygons that are shown on the map that are out of scope
- shapes
palette of symbol shapes. Only applicable if
shape
is a (vector of) categorical variable(s). See details for the shape specification. By default, the filled symbols 21 to 25 are taken.- shapes.legend
symbol shapes that are used in the legend (instead of the symbols specified with
shape
). These shapes will be used in the legends regarding thesize
andcol
of the symbols. Especially useful whenshapes
consist of grobs that have to be represented by neutrally colored shapes. See alsoshapes.legend.fill
.- shapes.legend.fill
Fill color of legend shapes. These colors will be used in the legends regarding the
size
andshape
of the symbols. See alsoshapes.legend
.- shapes.labels
Legend labels for the symbol shapes
- shapes.drop.levels
should unused symbol classes be omitted?
FALSE
by default.- shapeNA
the shape (a number or grob) for missing values. By default a cross (number 4). Set to
NA
to hide symbols for missing values.- shape.textNA
text used for missing values of the shape variable.
- shape.showNA
logical that determines whether missing values are named in the legend. By default (
NA
), this depends on the presence of missing values.- shapes.n
preferred number of shape classes. Only applicable when
shape
is a numeric variable name.- shapes.style
method to process the shape scale when
shape
is a numeric variable. Seestyle
argument for options.- shapes.style.args
arguments passed on to
classIntervals
(see alsoshapes.tyle
).- shapes.as.count
when
shape
is a numeric variable, should it be processed as a count variable? Seeas.count
argument for options.- shapes.breaks
in case
shapes.style=="fixed"
, breaks should be specified- shapes.interval.closure
value that determines whether where the intervals are closed:
"left"
or"right"
. Only applicable ifshape
is a numeric variable.- legend.max.symbol.size
Maximum size of the symbols that are drawn in the legend. For circles and bubbles, a value larger than one is recommended (and used for
tm_bubbles
)- just
justification of the symbols relative to the point coordinates. The first value specifies horizontal and the second value vertical justification. Possible values are:
"left"
,"right"
,"center"
,"bottom"
, and"top"
. Numeric values of 0 specify left alignment and 1 right alignment. The default value isc("center", "center")
. For icons, this value may already be speficied (seetmap_icons
). Thejust
, if specified, will overrides this.- jitter
number that determines the amount of jittering, i.e. the random noise added to the position of the symbols. 0 means no jittering is applied, any positive number means that the random noise has a standard deviation of
jitter
times the height of one line of text line.- xmod
horizontal position modification of the symbols, in terms of the height of one line of text. Either a single number for all polygons, or a numeric variable in the shape data specifying a number for each polygon. Together with
ymod
, it determines position modification of the symbols. See alsojitter
for random position modifications. In most coordinate systems (projections), the origin is located at the bottom left, so negativexmod
move the symbols to the left, and negativeymod
values to the bottom.- ymod
vertical position modification. See xmod.
- icon.scale
scaling number that determines how large the icons (or grobs) are in plot mode in comparison to proportional symbols (such as bubbles). In view mode, the size is determined by the icon specification (see
tmap_icons
) or, if grobs are specified bygrob.width
andgrob.heigth
- grob.dim
vector of four values that determine how grob objects (see details) are shown in view mode. The first and second value are the width and height of the displayed icon. The third and fourth value are the width and height of the rendered png image that is used for the icon. Generally, the third and fourth value should be large enough to render a ggplot2 graphic successfully. Only needed for the view mode.
- title.size
title of the legend element regarding the symbol sizes
- title.col
title of the legend element regarding the symbol colors
- title.shape
title of the legend element regarding the symbol shapes
- legend.size.show
logical that determines whether the legend for the symbol sizes is shown
- legend.col.show
logical that determines whether the legend for the symbol colors is shown
- legend.shape.show
logical that determines whether the legend for the symbol shapes is shown
- legend.format
list of formatting options for the legend numbers. Only applicable if
labels
is undefined. Parameters are:- fun
Function to specify the labels. It should take a numeric vector, and should return a character vector of the same size. By default it is not specified. If specified, the list items
scientific
,format
, anddigits
(see below) are not used.- scientific
Should the labels be formatted scientifically? If so, square brackets are used, and the
format
of the numbers is"g"
. Otherwise,format="f"
, andtext.separator
,text.less.than
, andtext.or.more
are used. Also, the numbers are automatically rounded to millions or billions if applicable.- format
By default,
"f"
, i.e. the standard notationxxx.xxx
, is used. Ifscientific=TRUE
then"g"
, which means that numbers are formatted scientifically, i.e.n.dddE+nn
if needed to save space.- digits
Number of digits after the decimal point if
format="f"
, and the number of significant digits otherwise.- big.num.abbr
Vector that defines whether and which abbrevations are used for large numbers. It is a named numeric vector, where the name indicated the abbreviation, and the number the magnitude (in terms on numbers of zero). Numbers are only abbreviation when they are large enough. Set it to
NA
to disable abbrevations. The default isc("mln" = 6, "bln" = 9)
. For layers wherestyle
is set tolog10
orlog10_pretty
, the default isNA
.- prefix
Prefix of each number
- suffix
Suffix of each number
- text.separator
Character string to use to separate numbers in the legend (default: "to").
- text.less.than
Character value(s) to use to translate "Less than". When a character vector of length 2 is specified, one for each word, these words are aligned when
text.to.columns = TRUE
- text.or.more
Character value(s) to use to translate "or more". When a character vector of length 2 is specified, one for each word, these words are aligned when
text.to.columns = TRUE
- text.align
Value that determines how the numbers are aligned,
"left"
,"center"
or"right"
. By default"left"
for legends in portrait format (legend.is.protrait = TRUE
), and"center"
otherwise.- text.to.columns
Logical that determines whether the text is aligned to three columns (from, text.separator, to). By default
FALSE
.- html.escape
Logical that determins whther HTML code is escaped in the popups in view mode. By default
TRUE
. If set toFALSE
HTML code can be added, e.g. to added white space via
.- ...
Other arguments passed on to
formatC
- legend.size.is.portrait
logical that determines whether the legend element regarding the symbol sizes is in portrait mode (
TRUE
) or landscape (FALSE
)- legend.col.is.portrait
logical that determines whether the legend element regarding the symbol colors is in portrait mode (
TRUE
) or landscape (FALSE
)- legend.shape.is.portrait
logical that determines whether the legend element regarding the symbol shapes is in portrait mode (
TRUE
) or landscape (FALSE
)- legend.size.reverse
logical that determines whether the items of the legend regarding the symbol sizes are shown in reverse order, i.e. from bottom to top when
legend.size.is.portrait = TRUE
and from right to left whenlegend.size.is.portrait = FALSE
- legend.col.reverse
logical that determines whether the items of the legend regarding the symbol colors are shown in reverse order, i.e. from bottom to top when
legend.col.is.portrait = TRUE
and from right to left whenlegend.col.is.portrait = FALSE
- legend.shape.reverse
logical that determines whether the items of the legend regarding the symbol shapes are shown in reverse order, i.e. from bottom to top when
legend.shape.is.portrait = TRUE
and from right to left whenlegend.shape.is.portrait = FALSE
- legend.hist
logical that determines whether a histogram is shown regarding the symbol colors
- legend.hist.title
title for the histogram. By default, one title is used for both the histogram and the normal legend for symbol colors.
- legend.size.z
index value that determines the position of the legend element regarding the symbol sizes with respect to other legend elements. The legend elements are stacked according to their z values. The legend element with the lowest z value is placed on top.
- legend.col.z
index value that determines the position of the legend element regarding the symbol colors. (See
legend.size.z
)- legend.shape.z
index value that determines the position of the legend element regarding the symbol shapes. (See
legend.size.z
)- legend.hist.z
index value that determines the position of the histogram legend element. (See
legend.size.z
)- id
name of the data variable that specifies the indices of the symbols. Only used for
"view"
mode (seetmap_mode
).- interactive
logical that determines whether this layer is interactive in view mode (e.g. hover text, popup, and click event in shiny apps)
- popup.vars
names of data variables that are shown in the popups in
"view"
mode. IfNA
(default), only aesthetic variables (i.e. specified bycol
andlwd
) are shown). If they are not specified, all variables are shown. Set popup.vars toFALSE
to disable popups. When a vector of variable names is provided, the names (if specified) are printed in the popups.- popup.format
list of formatting options for the popup values. See the argument
legend.format
for options. Only applicable for numeric data variables. If one list of formatting options is provided, it is applied to all numeric variables ofpopup.vars
. Also, a (named) list of lists can be provided. In that case, each list of formatting options is applied to the named variable.- zindex
zindex of the pane in view mode. By default, it is set to the layer number plus 400. By default, the tmap layers will therefore be placed in the custom panes
"tmap401"
,"tmap402"
, etc., except for the base tile layers, which are placed in the standard"tile"
. This parameter determines both the name of the pane and the z-index, which determines the pane order from bottom to top. For instance, ifzindex
is set to 500, the pane will be named"tmap500"
.- group
name of the group to which this layer belongs in view mode. Each group can be selected or deselected in the layer control item. Set
group = NULL
to hide the layer in the layer control item. By default, it will be set to the name of the shape (specified intm_shape
).- auto.palette.mapping
deprecated. It has been replaced by
midpoint
for numeric variables andstretch.palette
for categorical variables.- max.categories
deprecated. It has moved to
tmap_options
.- ...
arguments passed on to
tm_symbols
. Fortm_markers
, arguments can also be passed on totm_text
. In that case, they have to be prefixed withtext.
, e.g. thecol
argument should be namestext.col
.- title
shortcut for
title.col
fortm_dots
- legend.show
shortcut for
legend.col.show
fortm_dots
- legend.is.portrait
shortcut for
legend.col.is.portrait
fortm_dots
- legend.z
shortcut for
legend.col.z shortcut
fortm_dots
- text
text of the markers. Shown in plot mode, and as popup text in view mode.
- text.just
justification of marker text (see
just
argument oftm_text
). Only applicable in plot mode.- markers.on.top.of.text
For
tm_markers
, should the markers be drawn on top of the text labels?
Details
Small multiples can be drawn in two ways: either by specifying the by
argument in tm_facets
, or by defining multiple variables in the aesthetic arguments, which are size
, col
, and shape
. In the latter case, the arguments, except for the ones starting with legend.
, can be specified for small multiples as follows. If the argument normally only takes a single value, such as n
, then a vector of those values can be specified, one for each small multiple. If the argument normally can take a vector, such as palette
, then a list of those vectors (or values) can be specified, one for each small multiple.
A shape specification is one of the following three options.
A numeric value that specifies the plotting character of the symbol. See parameter
pch
ofpoints
and the last example to create a plot with all options. Note that this is not supported for the"view" mode.
A
grob
object, which can be a ggplot2 plot object created withggplotGrob
. To specify multiple shapes, a list of grob objects is required. See example of a proportional symbol map with ggplot2 plots.An icon specification, which can be created with
tmap_icons
.
To specify multiple shapes (needed for the shapes
argument), a vector or list of these shape specification is required. The shape specification options can also be mixed. For the shapes
argument, it is possible to use a named vector or list, where the names correspond to the value of the variable specified by the shape
argument.
For small multiples, a list of these shape specification(s) should be provided.
References
Flannery J (1971). The Relative Effectiveness of Some Common Graduated Point Symbols in the Presentation of Quantitative Data. Canadian Cartographer, 8(2), 96-109.
Tennekes, M., 2018, tmap: Thematic Maps in R, Journal of Statistical Software, 84(6), 1-39, doi:10.18637/jss.v084.i06
Examples
data(World, metro)
metro$growth <- (metro$pop2020 - metro$pop2010) / (metro$pop2010 * 10) * 100
tm_shape(World) +
tm_fill("grey70") +
tm_shape(metro) +
tm_bubbles("pop2010", col = "growth",
border.col = "black", border.alpha = .5,
style="fixed", breaks=c(-Inf, seq(0, 6, by=2), Inf),
palette="-RdYlBu", contrast=1,
title.size="Metro population",
title.col="Growth rate (%)") +
tm_format("World")
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> Variable(s) "growth" contains positive and negative values, so midpoint is set to 0. Set midpoint = NA to show the full spectrum of the color palette.
tm_shape(metro) +
tm_symbols(size = "pop2010", col="pop2010", shape="pop2010",
legend.format = list(text.align="right", text.to.columns = TRUE)) +
tm_legend(outside = TRUE, outside.position = "bottom", stack = "horizontal")
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
if (require(ggplot2) && require(dplyr) && require(tidyr) && require(tmaptools) && require(sf)) {
data(NLD_prov)
origin_data <- NLD_prov %>%
st_set_geometry(NULL) %>%
mutate(FID= factor(1:n())) %>%
select(FID, origin_native, origin_west, origin_non_west) %>%
gather(key=origin, value=perc, origin_native, origin_west, origin_non_west, factor_key=TRUE)
origin_cols <- get_brewer_pal("Dark2", 3)
grobs <- lapply(split(origin_data, origin_data$FID), function(x) {
ggplotGrob(ggplot(x, aes(x="", y=-perc, fill=origin)) +
geom_bar(width=1, stat="identity") +
scale_y_continuous(expand=c(0,0)) +
scale_fill_manual(values=origin_cols) +
theme_ps(plot.axes = FALSE))
})
names(grobs) <- NLD_prov$name
tm_shape(NLD_prov) +
tm_polygons(group = "Provinces") +
tm_symbols(size="population", shape="name",
shapes=grobs,
sizes.legend=c(.5, 1,3)*1e6,
scale=1,
legend.shape.show = FALSE,
legend.size.is.portrait = TRUE,
shapes.legend = 22,
title.size = "Population",
group = "Charts",
id = "name",
popup.vars = c("population", "origin_native",
"origin_west", "origin_non_west")) +
tm_add_legend(type="fill",
group = "Charts",
col=origin_cols,
labels=c("Native", "Western", "Non-western"),
title="Origin") +
tm_format("NLD")
}
#> Loading required package: ggplot2
#> Loading required package: tmaptools
#> Loading required package: sf
#> Linking to GEOS 3.10.2, GDAL 3.4.1, PROJ 8.2.1; sf_use_s2() is TRUE
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
#> old-style crs object detected; please recreate object with a recent sf::st_crs()
# TIP: check out these examples in view mode, enabled with tmap_mode("view")
if (FALSE) { # \dontrun{
if (require(rnaturalearth)) {
airports <- ne_download(scale=10, type="airports", returnclass = "sf")
airplane <- tmap_icons(system.file("img/airplane.png", package = "tmap"))
current.mode <- tmap_mode("view")
tm_shape(airports) +
tm_symbols(shape=airplane, size="natlscale",
legend.size.show = FALSE, scale=1, border.col = NULL, id="name", popup.vars = TRUE) +
tm_view(set.view = c(lon = 15, lat = 48, zoom = 4))
tmap_mode(current.mode)
}
} # }
#####################################################################################
if (FALSE) { # \dontrun{
# plot all available symbol shapes:
if (require(ggplot2)) {
ggplot(data.frame(p=c(0:25,32:127))) +
geom_point(aes(x=p%%16, y=-(p%/%16), shape=p), size=5, fill="red") +
geom_text(mapping=aes(x=p%%16, y=-(p%/%16+0.25), label=p), size=3) +
scale_shape_identity() +
theme(axis.title=element_blank(),
axis.text=element_blank(),
axis.ticks=element_blank(),
panel.background=element_blank())
}
} # }