Reputation: 852
I have code producing a swell plot in R. Check it out!
I made it using this code:
SwellPlot <- function(Data,P) {
par(mfcol=c(1,1), mar=c(4, 4.5, 0, 0) + 0.1)
plot(c(0.5,P+0.5), c(-0.5,P+0.5), type="n", cex=1, lab=c(20,20,1), cex.lab=1.5, yaxs="i", xaxs="i", xlab=~bold("Stuff!"), ylab=~bold("Other stuff!"))
for (f in 1:(P+1)) {
for (r in 0:P) {
points(r,(f-1), pch=15, cex=(60/P)*sqrt(Data[f,r]/200))
}
}
}
With Data
input as a matrix, like this one used for the above example:
Data <- matrix(c(0, 117, 76, 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 199, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 188, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 90,
109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 38, 143, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 18, 142, 39, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 8, 114, 75, 3, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 4, 95, 99, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 68, 121, 7, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 65, 122, 10,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,
120, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 42, 132, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 35, 135, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 44, 128, 27, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 33, 139, 27, 1, 0, 0, 0, 0,
0, 0, 0, 0), 17, 16, byrow=FALSE)
I would like to glom a vertical series of labels along the right side of my swell plot (these labels are different than the y-axis labels, which I need to remain as they already are). I have done so by extending the x-axis and using text(), but when I do this it looks kludgy (on the x-axis labels) and because I have plots with quite variable x-axis lengths I have to spend a lot of trial and error time making sure that the width of my labels does not overlap the right-most plotted elements. The improved plot would look kinda like this:
I imagine that there must be some relatively straightforward way of doing this using layout()
or mfcol
or somesuch, but the documentation and examples get rapidly complex for me. How would you solve this?
Bonus points for answers that permit me to specifically (1) make the width of the label column I would like to add 8% of the width of my swell plot, and (2) make my swell plot (not including the labels up the right side) retain its 1:1 aspect ratio.
Also bonus points if this can be done using par
and plot
and the like.
Upvotes: 0
Views: 155
Reputation: 206242
Here is one possibility. You can either add rownames
to your Data
or you can pass in a vector of names
SwellPlot <- function(Data,P=nrow(Data), labels=!is.null(rownames(Data))) {
par(mfcol=c(1,1), mar=c(4, 4.5, 0, 3) + 0.1)
plot(c(0.5,P+0.5), c(-0.5,P+0.5),
type="n", cex=1, lab=c(20,20,1),
cex.lab=1.5, yaxs="i", xaxs="i",
xlab=~bold("Stuff!"), ylab=~bold("Other stuff!")
)
cex<-(60/P)*sqrt(Data/200)
points(col(Data), row(Data), pch=15, cex=cex)
if(is.logical(labels) && labels) {
labels = rownames(Data)
}
if(is.character(labels)) {
axis(4, labels=labels, at=1:P, las=1, tick=F)
}
}
#add names for labeling
lbl<-c("",rev(c("Ant","Bat","Cat","Dog","Eel","Fly","Gar","Hog")), rep("",8))
rownames(Data)<-lbl
SwellPlot(Data)
I just drew the extra names with axis
and I made sure to make room for them by adjusting the par
I also edited the middle to take out the two loops. Those were pretty slow. You can do it all with one call to points passing all the x,y pairs at once. The trick is that if you pass a data.frame, it will convert it to a simple vector. So if all the matrices are arranges the same way, you'll get a point for each cell.
Upvotes: 1