Improving graph quality while exporting in r - r

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.

Related

How to specify breaks for y axis in R plot

I have created the following fanchart using the fanplot package. I'm trying to add axis ticks and labels to the y axis, however it's only giving me the decimals and not the full number. Looking for a solution to display the full number (e.g 4.59 and 4.61) on the y axis
I am also unsure of how to specify the breaks and number of decimal points for the labels on the y-axis using plot(). I know doing all of this in ggplot2 it would look something like this scale_y_continuous(breaks = seq(min(data.ts$Index),max(data.ts$Index),by=0.02)) . Any ideas on how to specify the breaks in the y axis as well as the number of decimal points using the base plot() feature in R?
Here is a reproductible of my dataset data.ts
structure(c(4.6049904235401, 4.60711076016453, 4.60980084146652,
4.61025389170935, 4.60544515681515, 4.60889021700954, 4.60983993107244,
4.61091608826696, 4.61138799159174, 4.61294431148318, 4.61167545843765,
4.61208284263432, 4.61421991328081, 4.61530485425155, 4.61471465043043,
4.6155992084451, 4.61195799200607, 4.61178486640435, 4.61037927954796,
4.60744590947049, 4.59979957741728, 4.59948551500254, 4.60078678080182,
4.60556092645471, 4.60934962087565, 4.60981147563749, 4.61060477704678,
4.61158365084251, 4.60963435263623, 4.61018215733317, 4.61209710959768,
4.61231368335184, 4.61071363571141, 4.61019496497916, 4.60948652606191,
4.61068813487859, 4.6084092003352, 4.60972706132393, 4.60866915174087,
4.61192565195909, 4.60878767339377, 4.61341471281265, 4.61015272152397,
4.6093479714315, 4.60750965935653, 4.60768790690338, 4.60676463096309,
4.60746490411374, 4.60885670935448, 4.60686846708382, 4.60688947889575,
4.60867708110485, 4.60448791268212, 4.60387348166032, 4.60569806689426,
4.6069320880709, 4.6087143894128, 4.61059688801283, 4.61065399116698,
4.61071421014339), .Tsp = c(2004, 2018.75, 4), class = "ts")
and here is a reproductible of the code I'm using
# # Install and Load Packages
## pacman::p_load(forecast,fanplot,tidyverse,tsbox,lubridate,readxl)
# Create an ARIMA Model using the auto.arima function
model <- auto.arima(data.ts)
# Simulate forecasts for 4 quarters (1 year) ahead
forecasts <- simulate(model, n=4)
# Create a data frame with the parameters needed for the uncertainty forecast
table <- ts_df(forecasts) %>%
rename(mode=value) %>%
mutate(time0 = rep(2019,4)) %>%
mutate(uncertainty = sd(mode)) %>%
mutate(skew = rep(0,4))
y0 <- 2019
k <- nrow(table)
# Set Percentiles
p <- seq(0.05, 0.95, 0.05)
p <- c(0.01, p, 0.99)
# Simulate a qsplitnorm distribution
fsval <- matrix(NA, nrow = length(p), ncol = k)
for (i in 1:k)
fsval[, i] <- qsplitnorm(p, mode = table$mode[i],
sd = table$uncertainty[i],
skew = table$skew[i])
# Create Plot
plot(data.ts, type = "l", col = "#75002B", lwd = 4,
xlim = c(y0 - 2,y0 + 0.75), ylim = range(fsval, data.ts),
xaxt = "n", yaxt = "n", ylab = "",xlab='',
main = '')
title(ylab = 'Log AFSI',main = 'Four-Quarter Ahead Forecast Fan - AFSI',
xlab = 'Date')
rect(y0 - 0.25, par("usr")[3] - 1, y0 + 2, par("usr")[4] + 1,
border = "gray90", col = "gray90")
fan(data = fsval, data.type = "values", probs = p,
start = y0, frequency = 4,
anchor = data.ts[time(data.ts) == y0 - .25],
fan.col = colorRampPalette(c("#75002B", "pink")),
ln = NULL, rlab = NULL)
# Add axis labels and ticks
axis(1, at = y0-2:y0 + 2, tcl = 0.5)
axis(1, at = seq(y0-2, y0 + 2, 0.25), labels = FALSE, tcl = 0.25)
abline(v = y0 - 0.25, lty = 1)
abline(v = y0 + 0.75, lty = 2)
axis(2, at = range(fsval, data.ts), las = 2, tcl = 0.5)
range(blah) will only return two values (the minimum and maximum). The at parameter of axis() requires a sequence of points at which you require axis labels. Hence, these are the only two y values you have on your plot. Take a look at using pretty(blah) or seq(min(blah), max(blah), length.out = 10).
The suggestions of #Feakster are worth looking at, but the problem here is that the y-axis margin isn't wide enough. You could do either of two things. You could round the labels so they fit within the margins, for example you could replace this
axis(2, at = range(fsval, data.ts), las = 2, tcl = 0.5)
with this
axis(2, at = range(fsval, data.ts),
labels = sprintf("%.3f", range(fsval, data.ts)), las = 2, tcl = 0.5)
Or, alternatively you could increase the y-axis margin before you make the plot by specifying:
par(mar=c(5,5,4,2)+.1)
plot(data.ts, type = "l", col = "#75002B", lwd = 4,
xlim = c(y0 - 2,y0 + 0.75), ylim = range(fsval, data.ts),
xaxt = "n", yaxt = "n", ylab = "",xlab='',
main = '')
Then everything below that should work. The mar element of par sets the number of lines printed in the margin of each axis. The default is c(5,4,4,2).

contourplot color and labels options in Lattice for R

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.

R: center red_to_blue color palette at 0 in levelplot

I am making a levelplot in which one variable of my data frame is used to color the cells (fold.change) and another (map.signif) is written on top. In this case, I write * and ** for significant cells.
This is my MWE:
set.seed(150)
pv.df <- data.frame(compound=rep(LETTERS[1:8], each=3), comparison=rep(c("a/b","b/c","a/c"), 8), p.value=runif(24, 0, 0.2), fold.change=runif(24, -0.3, 0.9))
pv.df$map.signif <- ifelse(pv.df$p.value > 0.05, "", ifelse(pv.df$p.value > 0.01,"*", "**"))
pv.df
myPanel <- function(x, y, z, ...) {
panel.levelplot(x, y, z, ...)
panel.text(x, y, pv.df$map.signif, cex=3)
}
#install.packages("latticeExtra")
library(latticeExtra)
library(RColorBrewer)
cols <- colorRampPalette(brewer.pal(11, "RdBu"))(11)
png(filename="test.png", height=800, width=400)
print(
levelplot(fold.change ~ comparison*compound, #p.value instead of p.adjust depending on map.signif
pv.df,
panel = myPanel,
col.regions = cols,
at = do.breaks(range(pv.df$fold.change), 11),
colorkey = list(col = cols,
at = do.breaks(range(pv.df$fold.change), 11)),
xlab = "", ylab = "", # remove axis titles
scales = list(x = list(rot = 45), # change rotation for x-axis text
cex = 0.8), # change font size for x- & y-axis text
main = list(label = "Test\nfold change color\n*pv<0.05\t**pv<0.01",
cex = 1.5))
)
dev.off()
Which produces:
My question here is: Since fold.change includes negative and positive values, how do I make 0 to coincide with white in my color palette, so negative values are in red, and positive ones in blue?
For the win, is it possible to wirte the * in black when the cell background is clear, and in white when the background is dark? Many thanks!
Your range is not simetrical. An alternative is this one:
max_abs <- max(abs(pv.df$fold.change))
brk <- do.breaks(c(-max_abs, max_abs), 11)
levelplot(fold.change ~ comparison*compound, #p.value instead of p.adjust depending on map.signif
pv.df,
panel = myPanel,
col.regions = cols,
at = brk,
colorkey = list(col = cols,
at = brk),
xlab = "", ylab = "", # remove axis titles
scales = list(x = list(rot = 45), # change rotation for x-axis text
cex = 0.8), # change font size for x- & y-axis text
main = list(label = "Test\nfold change color\n*pv<0.05\t**pv<0.01",
cex = 1.5))
Edit
If you don't want the extra breaks:
max_abs <- max(abs(pv.df$fold.change))
brk <- do.breaks(c(-max_abs, max_abs), 11)
first_true <- which.max(brk > min(pv.df$fold.change))
brk <- brk[(first_true -1):length(brk)]
cols <- cols[(first_true -1):length(cols)]
levelplot(fold.change ~ comparison*compound, #p.value instead of p.adjust depending on map.signif
pv.df,
panel = myPanel,
col.regions = cols,
at = brk,
colorkey = list(col = cols,
at = brk),
xlab = "", ylab = "", # remove axis titles
scales = list(x = list(rot = 45), # change rotation for x-axis text
cex = 0.8), # change font size for x- & y-axis text
main = list(label = "Test\nfold change color\n*pv<0.05\t**pv<0.01",
cex = 1.5))

How to add threshold line when there are multiple graphs?

I am using a function which plots two graphs on the same picture. I want to add threshold line to the first graph and a different threshold on the second graph. I am using abline() function to do so. chr6 comes with a library as an example.
install.packages("GenWin")
library(GenWin)
chrom_num = 6
jpeg(filename = paste(chrom_num, ".jpg", sep=""), width = 1200, height = 800)
chr = splineAnalyze(chr6$Fst, chr6$Position, plotRaw = 1, plotWindows = 1, method = 4)
abline(0.3, 0, col = "green")
abline(6, 0, col = "green")
Both threshold lines show up on the second graph. How to prevent this? In other word is there a way to direct to which graph I am adding something?
If you want to add something, I think it would be better to make graphs by yourself from the analyzed data, chr (almost all code is picked out from splineAnalyze). This approach would enable you to customize the graph.
analyzed_data <- chr # All you need to do is changing these lines and data and col names of 1st plot()).
smoothness <- 100 # default value
jpeg(filename = paste("file_name", ".jpg", sep=""), width = 1200, height = 800)
par(mfrow = c(2,1))
# 1st graph
plot(Fst ~ Position, chr6, xlab = "Position (bp)", ylab = "Raw values")
with(analyzed_data,
lines(x = seq(0, max(rawSpline$x), by = smoothness),
y = predict(rawSpline, seq(0, max(rawSpline$x), by = smoothness)), col = "red")
)
abline(0.3, 0, col = "green")
# 2nd graph
with(analyzed_data,
plot(x = (windowData$WindowStop - windowData$WindowStart)/2 + windowData$WindowStart,
y = windowData$Wstat, xlab = "Position (bp)", ylab = "Spline Wstat", pch = 19)
)
abline(6, 0, col = "green")
dev.off()
Of course, you can do it using splineAnalyze(..., plotRaw = 1, plotWindows = 1, ...) and adding the lines.
jpeg(filename = paste("file_name2", ".jpg", sep=""), width = 1200, height = 800)
chr = splineAnalyze(chr6$Fst, chr6$Position, plotRaw = 1, plotWindows = 1, method = 4)
abline(6, 0, col = "green") # draw on 2nd panel
layout(matrix(c(2,1), ncol = 1)) # refocus 1st panel
par(new = T)
plot(Fst ~ Position, chr6, ann = F, type = "n", axes = F) # reproduce the coordinates
abline(0.3, 0, col = "green") # draw on 1st panel
dev.off()

Put one line chart and bar chart in one plot in R (Not ggplot)?

how to
Combine a bar chart and line in single plot in R (from different data sources)?
Say I have two data sources as:
barData<-c(0.1,0.2,0.3,0.4) #In percentage
lineData<-c(100,22,534,52,900)
Note that they may not be in the same scale.
Can I plot both barData and LineData in one plot and make them good looking ?
I cant use ggplot in this case so this is not a duplicated question..
Something like the following:
Maybe this helps as a starting point:
par(mar = rep(4, 4))
barData<-c(0.1,0.2,0.3,0.4) * 100
y <- lineData<-c(100,22,534,900);
x <- barplot(barData,
axes = FALSE,
col = "blue",
xlab = "",
ylab = "",
ylim = c(0, 100) )[, 1]
axis(1, at = x, labels = c("Julia", "Pat", "Max", "Norman"))
ats <- c(seq(0, 100, 15), 100); axis(4, at = ats, labels = paste0(ats, "%"), las = 2)
axis(3, at = x, labels = NA)
par(new = TRUE)
plot(x = x, y = y, type = "b", col = "red", axes = FALSE, xlab = "", ylab = "")
axis(2, at = c(pretty(lineData), max(lineData)), las = 2)
mtext(text="Lines of code by Programmer", side = 3, line = 1)
box()

Resources