I am trying to join 4 graphs with the layout function. However, I only get 3 represented: all except the stem and leaf diagram.
In brief, this is what it looks like in r:
layout(matrix(c(1,2,3,4), 2, 2, byrow =TRUE))
stem(graph1)
boxplot(graph2)
hist(graph3)
barplot(graph4)
Why doesn't the stem graph plot the same as the others, and is there another function that can do it?
Thank you in advance
As #DaveArmstrong already hinted, stem outputs characters, which are printable but not plotable.
You could redirect the output from stem to a plot like so (shamelessly stolen from this SO answer):
layout(matrix(c(1,2,3,4), 2, 2, byrow =TRUE))
## start stem-plot
plot.new()
tmp <- capture.output(stem(c(10,11,20:23)))
text( 0,1, paste(tmp, collapse='\n'), adj=c(0,1), family='mono' )
## end stem-plot
boxplot(runif(100))
hist(rnorm(100))
barplot(1:3)
Related
Hello and thanks for reading!
I built an ecdf function using rstudio and I am trying to get the probabilities that correspond to certain points (list format). My R code looks like this:
input <- read.table('/home/agalvez/data/domains/test_ecdf.txt', sep="\t", header=TRUE)
#Build the function
myecdf <- ecdf(input$X118.4)
#Plot the function
plot(myecdf, main = "CDF", xlab = "Bit score", ylab = "Probability") +
abline(v = 25, col = "red")
#Extract probabilities
myecdf(100)
As you can see I am able to extract the probability of one point at a time. But if I try to get more than one I get an error message. I will now attach things that I have tried that did not work.
myecdf(100, 2, 4, ...)
Error in myecdf(100, 2, 4) : unused arguments (2, 4)
myecdf(100)
myecdf(2)
myecdf(4)
...
This approach gives me the results like this in the console:
> myecdf(100)
[1] 0.8048582
> myecdf(2)
[1] 1.382514e-05
> myecdf(4)
[1] 0.0005875684
I would like them to be a list.
myecdf(100,2,4,...)
Error in myecdf(100, 2, 4) : unused arguments (2, 4)
Any help would be really appreciated, sorry for disturbing with this simple question but I am pretty new to R and thanks in advance!
You have to define the wanted values as vector:
myecdf(c(100, 2, 4))
I am using the following formula to plot 5 graphs together :
my_data <- as.data.frame(datasets::volcano)
layout(matrix(c(1,2,3,4,5,6), 3, 2, byrow = TRUE))
par(mar=c(1,1,1,1))
plot(my_data$V1, my_data$V2)
plot(my_data$V3, my_data$V4)
plot(my_data$V5, my_data$V6)
plot(my_data$V7, my_data$V8)
plot(my_data$V9, my_data$V10)
plot.new()
It works well but I loose the scale of the y-axis of the 1, 3 and 5th plots and the x-axis of the latter. This keeps happening for any future ones I do until I dev.off().
Thanks!
You can use par(mfrow = c(3, 2)) and adjust your margins. You may need to increase the size of your window to accommodate the plot
my_data <- as.data.frame(datasets::volcano)
par(mfrow = c(3, 2))
par(mar = c(2, 2, 2, 2))
plot(my_data$V1, my_data$V2)
plot(my_data$V3, my_data$V4)
plot(my_data$V5, my_data$V6)
plot(my_data$V7, my_data$V8)
plot(my_data$V9, my_data$V10)
In addition to #AllanCameron's solution—I'd keep layout in mind, since it can be very useful! Also you may want to regard the RStudio "Plots" window as a preview tool. Better save your plots with pdf or png as shown below; the plot will be saved in your getwd(). In addition you may avoid the repeated plot call by creating a sub.cols data frame which can be looped by an sapply.
my_data <- as.data.frame(datasets::volcano)
sub.cols <- as.data.frame(matrix(1:10, 2))
png("myPlot01.png", width=400, height=600)
layout(matrix(1:6, 3, 2, byrow=TRUE))
op <- par(mar=c(4.5, 2.5, 1.5, 1.5)) ## set par and store old par
sapply(sub.cols, function(i) plot(my_data[i]))
plot.new()
par(op) ## restore old par
dev.off()
If the soiled console annoys you you can do invisible(sapply(.)) above.
The following is some code that produces various spider graphs:
# Data must be given as the data frame, where the first cases show maximum.
maxmin <- data.frame(
total=c(5, 1),
phys=c(15, 3),
psycho=c(3, 0),
social=c(5, 1),
env=c(5, 1))
# data for radarchart function version 1 series, minimum value must be omitted from above.
RNGkind("Mersenne-Twister")
set.seed(123)
dat <- data.frame(
total=runif(3, 1, 5),
phys=rnorm(3, 10, 2),
psycho=c(0.5, NA, 3),
social=runif(3, 1, 5),
env=c(5, 2.5, 4))
dat <- rbind(maxmin,dat)
op <- par(mar=c(1, 2, 2, 1),mfrow=c(2, 2))
radarchart(dat, axistype=1, seg=5, plty=1, vlabels=c("Total\nQOL", "Physical\naspects",
"Phychological\naspects", "Social\naspects", "Environmental\naspects"),
title="(axis=1, 5 segments, with specified vlabels)")
radarchart(dat, axistype=2, pcol=topo.colors(3), plty=1, pdensity=30, pfcol=topo.colors(3),
title="(topo.colors, fill, axis=2)")
radarchart(dat, axistype=3, pty=32, plty=1, axislabcol="grey", na.itp=FALSE,
title="(no points, axis=3, na.itp=FALSE)")
radarchart(dat, axistype=1, plwd=1:5, pcol=1, centerzero=TRUE,
seg=4, caxislabels=c("worst", "", "", "", "best"),
title="(use lty and lwd but b/w, axis=1,\n centerzero=TRUE, with centerlabels)")
par(op)
The output of the graphs consists of two sets of line segments with different colors. Where did the second set of line segments come from? Also what is a good way to graph multiple items on the same spider graph?
You should mention that you are using the fmsb library to create the graph. The code you show is the example in the documentation. The puzzling thing at first glance is why three sets of lines are shown (not two as you imply with "second set") while there are 5 records in dat.
It is all in that same documentation you took the code from:
row 1 = the maximum values (defined in `maxmin` in the example code)
row 2 = minimum values (defined in `maxmin` in the example code)
row 3 to 5 are example data points, each row leading to one of the
three line segments that you see in the example graphs.
Just read the documentation for radarchart {fmsb} again and play with the numbers in the example as you do so. It should be pretty clear what is happening and what options you have for your own data. You can add as many data-rows and create corresponding lines as you wish. But these do tend to become unreadable if you overdo it.
i am trying to display two or more heatmaps side by side in the same png or pdf . The layout or mfcol is not working in the case. Can someone please help me out with this.
Here's one option using the recently introduced gridGraphics package,
library(gridGraphics)
library(grid)
heatmap(as.matrix(mtcars))
library(gridGraphics)
grab_grob <- function(){
grid.echo()
grid.grab()
}
g <- grab_grob()
grid.newpage()
# library(gridExtra)
# grid.arrange(g,g, ncol=2, clip=TRUE)
lay <- grid.layout(nrow = 1, ncol=2)
pushViewport(viewport(layout = lay))
grid.draw(editGrob(g, vp=viewport(layout.pos.row = 1,
layout.pos.col = 1, clip=TRUE)))
grid.draw(editGrob(g, vp=viewport(layout.pos.row = 1,
layout.pos.col = 2, clip=TRUE)))
upViewport(1)
As stated in the help document for heatmap.2,
'heatmap.2()' uses 'layout' and draws the 'image' in the lower
right corner of a 2x2 layout. Consequentially, it can not be
used in a multi column/row layout, i.e., when 'par(mfrow= *)' or
'(mfcol= *)' has been called.
The same is true for heatmap.
Here's a way of doing that. It is very hacky but I think that when a function doesn't do what you want to do the best solution is to make it do it anyway.
Function heatmap.2 contains the following three lines at mid-way through its code:
...
op <- par(no.readonly = TRUE)
on.exit(par(op))
layout(lmat, widths = lwid, heights = lhei, respect = FALSE)
...
It is because of them that you can't use layout and par(mar=...) since it overrides it.
Copy the code of heatmap.2 into a new function (say heatmap.3) and remove those three lines:
heatmap.3 <- function(... #etc etc with the exact same code minus those 3 lines
Then your code to produce your two heatmaps side by side will be, for instance:
layout(rbind(c(4,3,8,7),c(2,1,6,5)),
widths = c(1,2,1,2), heights = c(1,2), respect = FALSE)
heatmap.3(x)
heatmap.3(y)
When preparing your layout remember that the heatmap code plot first the heatmap itself, then the "row" dendrogram, then the "col" dendrogram and finally the histogram, hence the order from top to bottom, left to right is 4, 3, 2, 1 meaning when both heatmap are side by side it becomes 4, 3, 8, 7, 2, 1, 6, 5.
After having exactly the same problem, I came up with the following solution:
1) Use ggplot2 to make your heatmap with dendrogram like here: Reproducing lattice dendrogram graph with ggplot2 and then arrange it with multiplot() function (http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_%28ggplot2%29/)
2) However, this is a lot of work and I wanted to stick with the base heatmap() function. The following is easy (though not plain R) and works on Linux if you have imagemagick installed:
m <- matrix(runif(10^2), ncol=10)
for (i1 in 1:4) {
ifile <- paste0(i1,'_heatmap.pdf')
pdf(ifile)
heatmap(m)
d <- dev.off()
}
system('montage -geometry 100% -tile 2x2 ./*_heatmap.pdf outfile.pdf')
Is there anyway to add a table to a plot. Suppose that I have the plot below:
curve(dnorm, -3, +4)
Now I like to add a matrix beneath the plot:
testMat <- matrix(1:20, ncol = 5)
My goal? I'm writing a plot function that not only does create a plot, but it also shows a matrix including the information I'm interested in underneath the plot.
Please see the attached picture to see what I mean.
I really appreciate your help.
There are probably better ways to do this, but one option might be to use one of the packages that "plots" matrices and data frames, like the "gplots" package.
Here is a very bare example (you can probably customize this for much finer control over the final layout).
# Some sample data
testMat <- matrix(1:20, ncol = 5)
testMatDF <- as.data.frame(testMat)
names(testMatDF) <- c("Hey there", "Column 2",
"Some * Symbols", "And ^ More",
"Final Column")
rownames(testMatDF) <- paste("Group", 1:4)
# Load the package
library(gplots)
# Set par for plotting a three-row plot
par(mfrow = c(3, 1))
curve(dnorm, -3, +4)
textplot(testMat)
textplot(testMatDF)
The result:
You can also use layout() instead of par(mfrow...) if you want to get a little bit more creative with the placement of your plots. For example:
layout(matrix(c(1, 1, 2, 3, 3, 3),
2, 3, byrow = TRUE))
curve(dnorm, -3, +4)
textplot(testMat)
textplot(testMatDF)
Package plotrix provides function addtable2plot.
Example from the help file:
library(plotrix)
testdf<-data.frame(Before=c(10,7,5),During=c(8,6,2),After=c(5,3,4))
rownames(testdf)<-c("Red","Green","Blue")
barp(testdf,main="Test addtable2plot",ylab="Value",
names.arg=colnames(testdf),col=2:4)
# show most of the options
addtable2plot(2,8,testdf,bty="o",display.rownames=TRUE,hlines=TRUE,
title="The table")
Edit:
Put the table in a new plot to place it underneath your plot.
library(plotrix)
layout(matrix(c(1,2), 2, 1, byrow = TRUE),
widths=c(1,1), heights=c(2,1))
testdf<-data.frame(Before=c(10,7,5),During=c(8,6,2),After=c(5,3,4))
rownames(testdf)<-c("Red","Green","Blue")
barp(testdf,main="Test addtable2plot",ylab="Value",
names.arg=colnames(testdf),col=2:4)
plot.new()
addtable2plot(0,0,testdf,bty="o",display.rownames=TRUE,hlines=TRUE,
title="The table")