I want to figure out how to build complex curved lines/polygons in R. We can easily draw a simple bezier line, e.g.
require(grid)
x <- c(0.25, 0.25, 0.75, 0.75)
y <- c(0.25, 0.75, 0.75, 0.25)
grid.newpage()
grid.bezier(x, y)
This method seems scale-constrained to 0-1 in both axes, and I'm not sure how to build beziers in a custom scale. I'm also unclear how R can bind these bezier objects together into polylines and ultimately polygons. If anyone can provide a minimal example I'd be very grateful. But alternatively a point in the right direction of documentation would greatly help, as I've not found a workflow so far. Thanks in advance.
As far as I understand grid.bezier you will have to chain individuals segments. This can be done via the id argument, but see also ?grig.bezier.
You can adjust the scale through viewports and the xscale and yscale.
library(grid)
x <- c(0.2, 0.2, 0.7, 0.4, 0.2, 0.2, 0.4, 0.4)
y <- c(0.2, 0.4, 0.7, 0.2, 0.2, 0, 0, 0.2)
grid.newpage()
grid.bezier(x, y, id=rep(1:2, each=4))
grid.newpage()
pushViewport(plotViewport(xscale=c(0, 10), yscale=c(0, 100)))
grid.xaxis()
grid.yaxis()
x <- x * 10
y <- y * 50
grid.bezier(x, y, id=rep(1:2, each=4), default.units="native")
Note that I used dataViewport which is just a convenience function wrapping viewport.
If you have the parametrization 'Y' of the curve you want to draw, you could just
t <- c(1:1000)*0.001
plot(t,Y(t))
or something like that.
Related
I want a lattice barchart that looks like ggplot barchart with reverse y axis from here
http://www.sthda.com/english/wiki/ggplot2-rotate-a-graph-reverse-and-flip-the-plot
In other words, I want to turn the barchart in lattice upside down, with the origin of bars at the top. I looked for the solution for quite some time thinking it should be easy, yet failed to find one...
require(lattice)
data <- data.frame(y = c(0.1, 0.4, 0.3, 0.23, 0.17, 0.27), x = c(1,2,3,4,5,6))
histogram <- barchart(data$y ~ data$x, horizontal = FALSE)
histogram
The code above produces regular barchart. What I want to do is to make bars start from the top, not from the bottom, with y scale reversed. In other words, I want this exact graph, but upside down.
Here's one trick to do that:
plot the -y instead of y, and specify that the origin is 0, then you can change the labels on the y axis as you see fit
mydata <- data.frame(y = c(0.1, 0.4, 0.3, 0.23, 0.17, 0.27), x = c(1,2,3,4,5,6))
# fix where you want the ticks to be
ticks_at <- seq(-0.5, 0, 0.1)
barchart(-y ~ x,
mydata,
horizontal = FALSE,
origin=0,
# set the position of the ticks and their labels
scales = list(y=list(at = ticks_at,
labels = -1 * (ticks_at))),
xlab = "x-Axis",
ylab ="y-Axis")
You'll get something like this :
I've got a graph, but the self-loops are large relative to the network, is there a way to reduce the self-loop size without changing the remainder of the graph?
Test data:
test.matrix=cbind(mtcars$gear,mtcars$carb)
adj.mat=get.adjacency(graph.edgelist(as.matrix(test.matrix)))
g=graph.adjacency(adj.mat,mode="undirected")
plot(g)
I tried changing the curve_multiple, to no avail, and can't find anything in the documentation relating to reducing loop size.
There is no option to the igraph plot function that allows you to change the size of the loops.
However, a small change to the igraph source code does the trick. You can see the igraph plot function by running
plot.igraph
You will find that the igraph plot function creates a function called loop. Inside that function you will find the lines:
cp <- matrix(c(x0, y0, x0 + 0.4, y0 + 0.2, x0 + 0.4,
y0 - 0.2, x0, y0), ncol = 2, byrow = TRUE)
you can make the loop half as wide/high by changing this to:
cp <- matrix(c(x0, y0, x0 + 0.2, y0 + 0.1, x0 + 0.2,
y0 - 0.1, x0, y0), ncol = 2, byrow = TRUE)
#desc commented that you can temporarily make this change to the igraph plot function source code with
trace("plot.igraph",edit=TRUE)
In Minitab, it is easy to create "cutpoint" histograms. Can this be done in ggplot2?
For example,
df <- data.frame(x = c(0.08, 0.21, 0.25, 0.4, 0.5, 0.6))
ggplot(df, aes(x = x)) + geom_histogram(binwidth = 0.1)
As you can see here, R defaults to "midpoint" histograms. The bar containing the 0.08 is being marked with a bar at the 0.1. The bar containing the 0.21 and 0.25 is being marked at the 0.2 and so forth.
Can I somehow change these bars so the first bar covers the area between 0 and 0.1, and the second bar covers the area between 0.2 and 0.3, and so forth?
You can get rid of the problem in two ways: using parameter "center" or using "boundary". With "center" you can specify the center of one of the bins, "boundary" is similar but you specify the value of a boundary between two bins. Worth noting that "center" and "boundary" can be either above or below the range of the data, in this case the value provided will be shifted of an adequate number of widths.
In this case you already know the width of the bin, its boundaries, so with this parameters you can easily do what you asked:
library(ggplot2)
df <- data.frame(x = c(0.08, 0.21, 0.25, 0.4, 0.5, 0.6))
# This is "center" solution:
ggplot(df, aes(x = x)) + geom_histogram(binwidth = 0.1, center=0.05)
# This is with "boundary" parameter
ggplot(df, aes(x = x)) + geom_histogram(binwidth = 0.1, boundary=0.1)
You can find details and more information on the reference ?geom_histogram.
Hope this helps
I have two plots that I would like to overlay in a particular way. Instead of side by side like when using par(), I would like one to sit inside the other, but be about a quarter the size.
More details: one of my plots is a map, another is a scatterplot with colored quadrants. The colored quadrants represent the colors plotted onto the map, so I would like to inset it nicely in the same plot as the map so that it serves as a legend.
Thanks in advance
Here's an example, although the links in comments point to similar approaches.
Grab a shapefile:
download.file(file.path('http://www.naturalearthdata.com/http/',
'www.naturalearthdata.com/download/50m',
'cultural/ne_50m_admin_1_states_provinces_lakes.zip'),
{f <- tempfile()})
unzip(f, exdir=tempdir())
Plotting:
library(rgdal)
shp <- readOGR(tempdir(), 'ne_50m_admin_1_states_provinces_lakes')
plot(subset(shp, admin=='Australia'),
col=sample(c('#7fc97f', '#beaed4', '#fdc086', '#ffff99'),
9, repl=TRUE))
opar <- par(plt=c(0.75, 0.95, 0.75, 0.95), new=TRUE)
plot.new()
plot.window(xlim=c(0, 1), ylim=c(0, 1), xaxs='i', yaxs='i')
rect(0, 0, 0.5, 0.5, border=NA, col='#7fc97f')
rect(0.5, 0, 1, 0.5, border=NA, col='#beaed4')
rect(0, 0.5, 0.5, 1, border=NA, col='#fdc086')
rect(0.5, 0.5, 1, 1, border=NA, col='#ffff99')
points(runif(100), runif(100), pch=20, cex=0.8)
box(lwd=2)
par(opar)
See plt under ?par for clarification.
This is how I did it in the past
grid.newpage()
vp <- viewport(width = 1, height = 1)
submain <- viewport(width = 0.9, height = 0.9, x = 0.5, y = 1,just=c("center","top"))
print(p, vp = submain)
subvp2 <- viewport(width = 0.2, height = 0.2, x = 0.39, y = 0.35,just=c("right","top"))
print(hi, vp = subvp2)
subvp1 <- viewport(width = 0.28, height = 0.28, x = 0.0, y = 0.1,just=c("left","bottom"))
print(ak, vp = subvp1)
in my case p, ak and hi were gg objects (maps created with ggplot) and I was inserting a small version of each near the main use map (p) - as it is typically done
If you take the code below, how can you change the filling of the third diamond, so it will be half-black, half-white? The solution should apply with any colors.
data <- c(1,2,3)
plot(data, pch=c(23,18,23), cex=c(2.5,3,2.5))
The pch characters are actual font symbols, so you will be limited to what is available in your fonts. Another alternative is to use the primitive plotting commands to make your own "symbols". This is very flexible, although there can be issues with resizing, etc., when mixing the two methods. This method is implemented in the nice my.symbols() example:
require(TeachingDemos)
bwDiamond <- function() {
plot.new()
polygon(c(0, 0.5, 1, 0.5, 0), c(0.5, 0, 0.5, 1, 0.5), lty=1)
polygon(c(0.25, 0.5, 1, 0.75, 0.25), c(0.25, 0, 0.5, 0.75, 0.25), col=1)
}
data <- c(1,2,3)
dev.new(width=4, height=4)
plot(data, type='n')
points(data[1:2], pch=c(23,18), cex=c(2.5,3))
my.symbols(data[3], data[3], symb=bwDiamond, symb.plots=TRUE, inches=0.22)
See also this Q/A: Point symbols in R
#JohnColby : Ok, here is a way to draw a half-coloured circle point, using grid.semicircle from lodplot package. It's not such tidy solution as yours with polygons, but it does the job:
require(lodplot)
dev.new(width=4,height=4)
plot(1:3,type="n")
grid.semicircle(100,150,10,5)#left circle on plot below
grid.semicircle(100,150,10,5,side=3,col=1)
grid.semicircle(200,150,10,5,side=2)#right circle on plot below
grid.semicircle(200,150,10,5,side=4,col=1)