JSS
JSS

Reputation: 203

tmap tm_dots behavior on user defined shape column

tm dots seems to have issues with a column that identifies the desired shape of a given observation

from the shapes enum:

0 = Open Square

1 = Open Circle

22 = Filled Square

21 = Open Circle

When I set the shape argument to 'shapeCol' where shapeCol is a column of 0 / 1 (open shapes), it returns a filled but otherwise correct shape

When I manually set the shape to 0 it returns the correct open shape but I need this shape to vary by observation

create data frame of random spatial data

library(sf)
library(tmap)
library(dplyr)

newDf <- data.frame(location=letters[1:30],
                lat=32+runif(30,0.01,0.03),
                lon=-97+runif(30,.01,.03)) %>%
                mutate(rowID=1:n(),
                reservoir=case_when(rowID<=15 ~ 'Codell',
                TRUE ~'Niobrara'))

newSf <- st_as_sf(newDf,coords=c('lon','lat'),crs=4326)

assign shape values / numeric index

shapes <- c('Niobrara'='circle',
            'Codell'='square')

shapeVals <- c('circle'=21,'square'=22,'triangleup'=24,'diamond'=23,'triangleDown'=25)
borderVals <- c('circle'=0,'square'=1,'triangleup'=2,'diamond'=5,'triangleDown'=6)


newSf.fin <- newSf %>% mutate(shapeType = shapes[reservoir],
                           shapeCol = as.factor(shapeVals[shapeType]),
                           borderCol = as.factor(borderVals[shapeType]))

newSf.fin %>% select(borderCol) # 0 and 1 / Open Shapes

#returns filled shapes despite shape column only referencing open values
tm_shape(newSf.fin) + tm_dots(shape='borderCol',size=2)

incorrect

#returns open shapes by manually setting shape value
tm_shape(newSf.fin) + tm_dots(shape=0,size=2)

correct

I know that this could be alleviated by map/looping but color scales would be more problematic and difficult. Is there a way to achieve correct open shapes based off a column value?

Upvotes: 1

Views: 1798

Answers (1)

Humpelstielzchen
Humpelstielzchen

Reputation: 6441

I'm no tmap expert, but this seems to be a misunderstanding.

In the documentation it says about the shape argument:

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. See details for the shape specification.

And about the shapes argument it says:

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.

So when you do shape = 0 you're doing a direct shape specification. That's why it works. When you use a variable name you need to map it's categories to the shapes-argument. You're not doing that so it takes 21 and 22, which are its default shapes and these are filled square and filled circle.

That's how it worked for me:

tm_shape(newSf.fin) + tm_dots(shape= 'borderCol',size=2, shapes = c(1, 0))

Upvotes: 2

Related Questions