I know this is a little rookie, but I've created a wes_palette like this:
rnq<-wesanderson::wes_palette("Zissou", 5, "discrete")
to plot an interval of values from 0 to 4.
But I have a single value in my data that is 9, and I would like to disclose it, using, for example, black.
Im using spplot:
rng = seq(0, 4, length=5)
rnq<-wesanderson::wes_palette("Zissou", 5, "discrete")
scale = list("SpatialPolygonsRescale", layout.scale.bar(),
offset = c(-900000,-1100000),
scale = 300000, fill=c("transparent","black"))
text1 = list("sp.text", c(-900000,-1150000), "0")
text2 = list("sp.text", c(-550000,-1150000), "300 Km")
text4<-list("sp.text", c( -730000, -1270000), cex=0.6, "Projection: EPSG 102003")
arrow = list("SpatialPolygonsRescale", layout.north.arrow(),
offset = c(-900000, -400000), scale = 200000)
spplot(spdf_img, "re1", col = "white", at = rng,
col.regions = rnq,
colorkey = list(
space = "bottom", labels=list(
at=round(rng, 1))),
sp.layout=list(scale, text1, text2, text4, arrow),
par.settings = list(axis.line = list(col = NA)))
Mainly, I don't know how to define my interval("rnq"), plus the color ramp and then the cuts (at argument in spplot) to change the value 9 to black.
The map is this:
gh
And the white polygon is the one I need to change the color.
Add the value 9 and the color black at your current rng and rnq:
rng <- c(rng,9)
rnq <- c(rnq,"black")
Then your code should work.
Yes, I managed to fix it, with more or less your code.
rng = c(seq(0, 4, length=5), 9)
rnq = c("#3B9AB2", "#78B7C5", "#EBCC2A", "darkorange1", "#F21A00")
Anyway, Thank you ;)
Related
I have written following code for comparing between to different variables over a period. The code works fine but only problem is when i output the file as "jpeg" the lines are not smooth and my arrow is not as smooth as i like it to be in other words the graph feels very low quality. But when i output it as "pdf" i get smooth lines and graph is of higher quality. But pdf files are high in file size and i need to insert these graphs in word file. I find it relatively easy to append jpeg into the word file. So is it possible to improve image quality while being in jpeg format. I tried using res argument in jpeg() but it doesnot output the graph as it is displayed in the rstudio.
I will appreciate the help. Thanks!
code:
library(shape)
library(Hmisc)
### samples ######
xaxs = seq(1,30,length=30)
precip = sample(200:800, 30)
ero = sample(0:10, 30, replace = T)
#########
svpth = getwd()
nm = "try.jpeg"
jpeg(paste0(svpth,"/",nm), width=950 , height =760, quality = 200, pointsize =15)
par(mar= c(5,4,2,4), oma=c(1,1,1,1))
plot(xaxs,precip, type = "p", pch=15, col="green", ylim = c(200,1000),
xlab = "Year" , ylab = "", cex.main=1.5, cex.axis=1.5, cex.lab=1.5)
lines(xaxs, precip,lty =1, col="green")
# xtick<-seq(0,30, by=1)
# axis(side = 1, at=xtick, labels = FALSE )
minor.tick(nx=5, ny=2, tick.ratio=0.5, x.args = list(), y.args = list())
mtext("Depth (mm)", side = 2, line = 2.7, cex = 1.5)
par(new=T)
plot(xaxs, (ero * 10), ylim = c(0,max(pretty(range((ero * 10))))+20), type = "p", pch=20, cex=1.5, col="red", axes = F, xlab = "", ylab = "")
lines(xaxs, (ero * 10),lty =2, col="red")
axis(side = 4, at=pretty(range((ero * 10))), cex.axis = 1.5)
# mtext("Erosion (t/ha/yr)", side = 4, line = 2.2, cex = 1.5)
mtext(expression(paste("Erosion (t ", ha^-1, yr^-1, ")")), side = 4, line = 2.7, cex = 1.5)
legend("topleft", legend = c("Precipitation","Erosion"), lty = c(1,2), pch = c(15,20), col = c("green","red"), cex = 1.6, bty = "n")
####arrow
Arrows(7, 85, 11, 90,lwd= 1.1)
Arrows(26, 85, 21, 90, lwd= 1.1)
txt = "High erosion rates in \nwheat-planting years"
xt = 16
yt = 85
text(xt, yt, labels = txt, family="serif", cex = 1.23)
sw = strwidth(txt)+1.4
sh = strheight(txt) +6
frsz = 0.38
rect(xt - sw/2 - frsz, yt - sh/2 - frsz, xt + sw/2 + frsz, yt + sh/2 + frsz-1)
# legend(15,80, legend = c("High erosion rates in \nwheat-planting years\n"),
# xjust = 0.5, yjust = 0.5)
dev.off()
It didn't use base R, but this makes an svg, which is smaller than a jpeg and will create some beautiful images. MS Word has no problems with svg, either.
The svg-- 18 kb; the jpeg-- 592 kb for the same image.
Use if it works, if not, well, perhaps someone else could use it? This won't show in the plot pane in RStudio, it will show in the viewer pane.
After the code, I have an image of saving the plot in the viewer pane in RStudio.
library(plotly)
df = data.frame("Year" = xaxs, "Depth" = precip, "Erosion" = ero *10)
p = plot_ly(df) %>%
add_trace(x = ~Year, y = ~Depth,
type = 'scatter', mode = 'lines', # to have both the points and lines use 'lines+markers'
name = "Depth",
line = list(shape = "spline", # smooth the curves in the lines (not that effective with lines+markers)
color = "green")) %>%
add_trace(x = ~Year, y = ~Erosion,
mode = 'lines',
name = "Erosion",
yaxis = "y2", # second y axis
line = list(dash = 'dash', # dash the lines
shape = "spline", # smooth the curves in the lines
color = "red")) %>% # without "lines+markers" spline will smooth out the points of the line
add_annotations(inherit = F, # add the arrows at the top of the plot
x = list(12, 18), # this is plot coordinates
y = list(800, 800),
ax = list(-60, 60), # this is pixels
ay = list(10, 10),
showarrow = T,
text = "") %>%
add_annotations(inherit = F, # add the textbox at the top of the plot
x = 15, y = 800,
ax = 0, ay = 0,
showarrow = F,
bordercolor = 'black',
text = "High erosion rates in\nwheat-planting years") %>%
layout(yaxis2 = list(overlaying = "y", side = "right", # add labels
title = paste0("Erosion (t ",
"ha<sup>-1</sup>",
"yr<sup>-1</sup>",
")")),
yaxis = list(title = "Depth (mm)"),
legend = list(x = .1, y = 1000),
margin = list(r = 80)) # right margin space for label
To save it, add the functionality. The icons at the top of the plot in the image at the end won't show until you hover over them. I think you may find that if you use this, the height/width specifications you have aren't the best fit anymore.
(p <- p %>% config( # save the plot; add a save function to the plot
toImageButtonOptions = list(
format = "svg",
filename = "try",
width = 950,
height = 760)) # end config
) # end () for print simo object assignment
The plot. The width and height in this image are 950 x 550.
I am quite new to Lattice and I am stuck with some possibly basic coding. I am using shapefiles and geoTIFFS to produce maps of animals distribution and in particular I have:
1 x point shapefile
2 x geoTIFF
1 x polygon shapefile
I am overlapping a levelplot of one of the geoTIFF (UD generated with adehabitatHR) with a contourplot of the same geoTIFF at specific intervals (percentile values), a contourplot of the second geoTIFF (depth raster from ETOPO2) for three specific values (-200, -1000 and -2000), the point shapefile (animal locations) and the polygon shapefile (land). All works fine but I need to change the font size of contour plot labels, their length (i.e. from 0.12315 to 0.123) and positioning for all the contourplots. For the depth contourplot I would like to change the style of each line in something like "continous line", "dashed line" and "point line", and for the contourplot of the UD I would like to change the color of each line using a yellow to red palette.
As far as I understand, I should use panel functions to implement these changes (e.g. Controlling z labels in contourplot) but i am not quite sure how to do it. Part of my code to generate the "plot":
aa <-
quantile(
UD_raster,
probs = c(0.25, 0.75),
type = 8,
names = TRUE
)
my.at <- c(aa[1], aa[2])
depth<-c(-100, -200, -2000)
levelplot(
UD_raster,
xlab = "",
ylab = "",
margin = FALSE,
contour = FALSE,
col.regions = viridis(100),
main = "A",
maxpixels = 2e5
) + layer(sp.polygons(Land, fill = "grey40", col = NA)) + layer(sp.points(locations, pts = 2, col = "red")) + contourplot(
UD_raster,
at = my.at,
labels = TRUE,
margin = FALSE
) + contourplot(
ETOPO2,
at = depth,
labels = TRUE,
margin = FALSE
)
A simplified image, with no UD layer and no point shapefile can be found here and as you can see it is pretty messy. Thanks for your help.
So far for the ETOPO2 countourplot I have solved by eliminating the labels and adding the argument lty to style the line. Because I can't figure out how to use lty with different values for each single line in my contour, I have replicated the contourplot function three times on the same surface, one for each contour I am interested into (this was easy because I only need three contours).
For the position, font and font size of the labels of the remaining contourplot I have used
labels = list(cex = 0.8, "verdana"),
label.style = "flat"
To "shorten" the length of the labels I have used the function round where I specify to which decimal digit to round number.
So now my new code looks like:
aa <-
quantile(
UD_raster,
probs = c(0.25, 0.75),
type = 8,
names = TRUE
)
my.at <- c(aa[1], aa[2])
my.at <- round(my.at, 3)
levelplot(
UD_raster,
xlab = "",
ylab = "",
margin = FALSE,
contour = FALSE,
col.regions = viridis(100),
main = "A",
maxpixels = 2e5
) + layer(sp.polygons(Land, fill = "grey40", col = NA)) + layer(sp.points(positions, pts = 2, col = "red")) + contourplot(
UD_raster,
at = my.at,
labels = list(cex = 0.8, "verdana"),
label.style = "flat",
margin = FALSE
) + contourplot(
ETOPO2,
at = -200,
labels = FALSE,
margin = FALSE,
lty = 1,
pretty = TRUE
) + contourplot(
ETOPO2,
at = -1000,
labels = FALSE,
margin = FALSE,
lty = 2,
pretty = TRUE
) + contourplot(
ETOPO2,
at = -2000,
labels = FALSE,
margin = FALSE,
lty = 3,
pretty = TRUE
)
As one could expect, it takes a bit longer to produce the plot. Still no idea on how to change the colors of the UD contourplot.
I've looked at this one but does not help with the random part. Is there a better way to randomly generate 3 different colors so that the square, the circle, and the text stand out visually from one another in the code below. The colors have to be randomly generated and also distinct enough from one another. The current code works maybe only half the time
plot(0, type = "n", xlim = c(0,10), ylim = c(0,10),
ann = FALSE, axes = FALSE, asp = 1)
cols = colorRampPalette(sample(2:9,2), alpha = TRUE)(8)
polygon(x = c(1,9,9,1), y = c(1,1,9,9), border = NA, col = cols[1])
symbols(x = 5, y = 5, circles = 4, inches = FALSE,
add = TRUE, bg = cols[4], fg = NA)
text(x = 5, y = 5, labels = "Hi", col = cols[7], font = 2, cex = 3)
EXAMPLES
GOOD
POLYGON: "#FF00FFFF", CIRCLE: "#916DFFFF", TEXT: "#24DAFFFF"
BAD
POLYGON: "#00FFFFFF", CIRCLE: "#51E3E3FF", TEXT: "#A2C7C7FF"
My original answer, which uses the hcl color space, often generated color combinations that were hard to distinguish. This updated answer uses the Lab color space, which is scaled based on the perceptual distance between colors, so similar distances in Lab space should correspond to similar perceptual color differences. In Lab, L is luminance or brightness on a scale of 0 to 100. a represents green to red, and b represents blue to yellow, with both on a scale of -100 to 100.
The code below generates two random values for a and b. If we think of these two values as representing a point in the ab plane, we generate two more colors with maximum perceptual distance from each other by rotating this point first by 120 degrees and then by 240 degrees. We then choose a single L value to give us three equally spaced colors.
Below I've packaged this in a function to make it easy to generate several plots with random colors. I've also set a minimum absolute value for a and b so that we don't get colors that are too similar, and included an Lval argument for choosing the L value of the Lab colors.
Based on a several runs, it looks like this approach performs much better than my original hcl version (although this may be due not only to the use of Lab space instead of hcl space, but also because I used only one dimension of hcl space but two dimensions of Lab space).
library(colorspace)
random.colors = function(Lval=80, ABmin=50) {
# 120 deg rotation matrix
aa = 2*pi/3
rot = matrix(c(cos(aa), -sin(aa), sin(aa), cos(aa)), nrow=2, byrow=TRUE)
# Generate random A and B points in LAB space
x = runif(2, ABmin, 100) * sample(c(-1,1), 2,replace=TRUE)
# Create three equally spaced colors in Lab space and convert to RGB
cols = LAB(cbind(rep(Lval,3), rbind(x, x %*% rot, x %*% rot %*% rot)))
cols = rgb(convertColor(cols#coords, from="Lab", to="sRGB"))
plot(0, type = "n", xlim = c(0,10), ylim = c(0,10),
ann = FALSE, axes = FALSE, asp = 1)
polygon(x = c(1,9,9,1), y = c(1,1,9,9), border = NA, col = cols[1])
symbols(x = 5, y = 5, circles = 4, inches = FALSE,
add = TRUE, bg = cols[2], fg = NA)
text(x = 5, y = 5, labels = "Hi", col = cols[3], font = 2, cex = 3)
}
par(mfrow=c(3,3), mar=rep(0,4))
replicate(9,random.colors())
For simplicity, the example above constrains the a and b values to be a constant distance from the origin (in ab-space) and uses the same L value for all three colors. You could instead extend this method to use all three dimensions of the Lab space. In addition, instead of requiring a constant distance from the origin, you could pick the first color at random and then require that the next two colors be picked such that all three colors are maximally separated from each other in Lab space.
Original Answer
You could generate colors that are equally spaced in the hue dimension (that is, have the maximum possible hue separation from each other). For example:
set.seed(60)
cols = hcl(runif(1,0,359.99) + c(0,120,240), 100, 65)
plot(0, type = "n", xlim = c(0,10), ylim = c(0,10),
ann = FALSE, axes = FALSE, asp = 1)
polygon(x = c(1,9,9,1), y = c(1,1,9,9), border = NA, col = cols[1])
symbols(x = 5, y = 5, circles = 4, inches = FALSE,
add = TRUE, bg = cols[2], fg = NA)
text(x = 5, y = 5, labels = "Hi", col = cols[3], font = 2, cex = 3)
Here are nine more random draws. As you can see, there are some combinations that don't work too well. But perhaps you can play around with different ways of slicing up the color space to see if you can get something better.
One super simple way would be to sample among the eight "standard" colours.
par(mar=c(0, 0, 0, 0))
set.seed(1)
plot(0, type = "n", xlim = c(0,10), ylim = c(0,10),
ann = FALSE, axes = FALSE, asp = 1)
cols <- sample(2:8, 3)
polygon(x = c(1,9,9,1), y = c(1,1,9,9), border = NA, col = cols[1])
symbols(x = 5, y = 5, circles = 4, inches = FALSE,
add = TRUE, bg = cols[2], fg = NA)
text(x = 5, y = 5, labels = "Hi", col = cols[3], font = 2, cex = 3)
Does anyone know of a way to 1) complete the missing gridlines in the grid3d call for y, and 2) draw horizontal gridlines to close the top of the grids constructed by the grid3d calls for x and y? I've played around with various combinations of pretty calls within grid3d to no avail and am wondering if this is an rgl quirk or a misspecification on my part. Additionally, I'd like to extend the vertical axis numbering to wherever the closed grids end up.
library(rgl)
cpts <- seq(0, 2, length = 40)
spts <- seq(0, 1, length = 20)
grid <- expand.grid(s=spts, c=cpts)
UFn <- function(s,c){c^(0.5) - exp(s) + 1}
U <- UFn(grid$s, grid$c)
open3d()
rgl.surface(x = spts, y = matrix(U,nrow = 40, ncol = 20), z = cpts,
coords = c(1,3,2), specular = "black")
axes3d("x", at = pretty(spts, n = 2), color = "black")
axes3d("y", at = pretty(cpts, n = 5), color = "black")
axes3d("z--", color = "black")
grid3d("x")
grid3d("y", at = pretty(spts, n = 2))
title3d(xlab ='s', ylab = 'c', zlab = 'U', color = "black")
rgl.snapshot("3d.png")
I would say it is a bug. You don't get any z-lines when using grid3d("y",n=2) even though it should be the same. You can work around it by using the list specification of at, setting the x element of the list, eg:
grid3d("y", at = list(x=pretty(spts, n = 2)))
I'm using base R plotting functions to produce a pie chart and I want to change the line thickness of the outlines of each pie segment. ?pie seems to indicate that I can add optional graphic parameters, but adding lwd= does not appear to work. Anyone have any clues as to how I might be able to do this. I'm not yet proficient in producing pie charts in ggplot, and would like to stick with base R plotting (if possible).
library(RColorBrewer)
x1 <- data.frame(V1 = c(200, 100)) ## generate data
row.names(x1) <- c("A", "B")
x1$pct <- round((x1$V1/sum(x1$V1))*100, 1)
lbls1 <- paste(row.names(x1), "-(",x1$pct, '%)', sep='') ## add some informative stuff
pie(x1$V1, labels=lbls1, col=tail(brewer.pal(3, 'PuBu'), n=2),
main=paste('My 3.1415'), cex=1.1, lwd= 3)
Notice lwd= does not increase line thickness like it would in other base plotting.
Anyone have any clues?
The call to polygon and lines within pie does not pass ... or lwd
...
polygon(c(P$x, 0), c(P$y, 0), density = density[i], angle = angle[i],
border = border[i], col = col[i], lty = lty[i])
P <- t2xy(mean(x[i + 0:1]))
lab <- as.character(labels[i])
if (!is.na(lab) && nzchar(lab)) {
lines(c(1, 1.05) * P$x, c(1, 1.05) * P$y)
....
You can get around this by setting par(lwd = 2) (or whatever) outside and prior to your call to pie
i.e.
# save original settings
opar <- par(no.readonly = TRUE)
par(lwd = 2)
pie(x1$V1, labels=lbls1, col=tail(brewer.pal(3, 'PuBu'), n=2),
main=paste('My 3.1415'), cex=1.1)
par(lwd = 3)
# reset to original
par(opar)
At the moment, the function inside pie that does the actual drawing is polygon and here is how it is called:
polygon(c(P$x, 0), c(P$y, 0), density = density[i], angle = angle[i],
border = border[i], col = col[i], lty = lty[i])
Notice there is no lwd argument and more critically no ... argument to accept arguments that might not have been hard coded.
Create a new pie2 function. First type pie, copy the code and make a few changes:
pie2 <-
function (x, labels = names(x), edges = 200, radius = 0.8, clockwise = FALSE,
init.angle = if (clockwise) 90 else 0, density = NULL, angle = 45,
col = NULL, border = NULL, lty = NULL, main = NULL, lwd=1,...)
{
................
polygon(c(P$x, 0), c(P$y, 0), density = density[i], angle = angle[i],
border = border[i], col = col[i], lty = lty[i], lwd=lwd )
.................
}
pie2(x1$V1, labels=lbls1, col=tail(brewer.pal(3, 'PuBu'), n=2),
main=paste('My 3.1415'), cex=1.1, lwd=5)