How to create histogram plot in ggplot2 without data frame? - r

I am plotting two histograms in R by using the following code.
x1<-rnorm(100)
x2<-rnorm(50)
h1<-hist(x1)
h2<-hist(x2)
plot(h1, col=rgb(0,0,1,.25), xlim=c(-4,4), ylim=c(0,0.6), main="", xlab="Index", ylab="Percent",freq = FALSE)
plot(h2, col=rgb(1,0,0,.25), xlim=c(-4,4), ylim=c(0,0.6), main="", xlab="Index", ylab="Percent",freq = FALSE,add=TRUE)
legend("topright", c("H1", "H2"), fill=c(rgb(0,0,1,.25),rgb(1,0,0,.25)))
The code produces the following output.
I need a visually good looking (or stylistic) version of the above plot. I want to use ggplot2. I am looking for something like this (see Change fill colors section). However, I think, ggplot2 only works with data frames. I do not have data frames in this case. Hence, how can I create good looking histogram plot in ggplot2? Please let me know. Thanks in advance.

You can (and should) put your data into a data.frame if you want to use ggplot. Ideally for ggplot, the data.frame should be in long format. Here's a simple example:
df1 = rbind(data.frame(grp='x1', x=x1), data.frame(grp='x2', x=x2))
ggplot(df1, aes(x, fill=grp)) +
geom_histogram(color='black', alpha=0.5)
There are lots of options to change the appearnce how you like. If you want to have the histograms stacked or grouped, or shown as percent versus count, or as densities etc., you will find many resources in previous questions showing how to implement each of those options.

Related

How do I make nested x-labels like a JMP variability plot, but using ggplot2

I love the JMP variability plot. (link) It is a powerful tool.
The example the plot has 2 x-axis labels, one for part-number and one for operator.
Here the JMP variability plot displays more than 2 levels of variables. The following splits by oil amount, batch size, and popcorn type. It can take some work to find the right sequence to show strongest separation, but this is an excellent tool for communication of information.
How does one do this, the multiple-level x-labels, with R using the ggplot2 library?
The best that I can find is this (link, link), which separates based on cylinder count, but does not make the x-axis labels.
My example code is this:
#reproducible
set.seed(2372064)
#data (I'm used to reading my own, not using built-in)
data(mtcars)
attach(mtcars)
#impose factors as factors
fact_idx <- c(2,8:11)
for(i in fact_idx){
mtcars[,i] <- as.factor(mtcars[,i])
}
#boxplot
p <- ggplot(mtcars, aes(gear, mpg, fill=cyl)) +
geom_boxplot(notch = TRUE)
p
The plot this gives is:
How do I make the x-axis lables indicate both gears and cylinders?
In jmp I get this:
You could use R-package VCA which comes with function varPlot implementing variability charts similar to JMP. There are multiple examples provided in the help. Your example would look like this:
library(VCA)
dat <- mtcars[order(mtcars$cyl, mtcars$gear),]
# default
varPlot(mpg~cyl/gear, dat)
# nicely formatted
varPlot(mpg~cyl/gear, dat,
BG=list(var="gear", col=paste0("gray", c(90,80,70)),
col.table=T),
VLine=list(var="cyl"), Mean=NULL,
MeanLine=list(var=c("cyl", "gear"), col=c("blue", "orange"),
lwd=c(2,2)),
Points=list(pch=16, cex=1))

R plot overlay barplot with plot type "p" (confused with factors)

I'm new to R. Previously, I've been able to overlay 2 separate plots that were of the same kind, p1 and p2, using plot (p1); plot (p2, add=T).
I'm struggling with the definition of factors when overlaying a barplot with a point plot showing all individual points.
I can individually plot the barplot as I want it. The point plot looks like I want it, but I realize I'm using an incorrect definition of phase as numerical to force R plot to display each value, rather than default to a boxplot (like when I use plot(my.df$cond, my.df$val).
Any tips on defining my variable types correctly or whether I'm using the correct barplot and plot functions, would be greatly appreciated. Thank you so much.
shpad <- c(1,2,5,6,1,2,5,6,1,2,5,6,1,2,5,6)
my.df <- data.frame(val=c(0.0738,0.0518,0.002,0.0397,0.1452,0.1152,0.1774,0.0658,0.0218,0.0497,-0.0296,0.0653,0.0848,0.1296,0.1416,0.0923,
phase=c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4),
sub=c(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4),
cond=c("NsNm", "NsNm", "NsNm", "NsNm", "NsLm", "NsLm", "NsLm", "NsLm", "LsNm", "LsNm", "LsNm", "LsNm", "LsLm", "LsLm", "LsLm", "LsLm"))
avg <-tapply(my.df$val, my.df$phase, mean)
barplot(avg, border=NA, names.arg=c("NsNm", "NsLm", "LsNm", "LsLm"),col=c("blue","darkblue","red", "darkred"),ylab = "score",ylim=c(-0.03,0.25))
plot(my.df$phase, my.df$val, type="p", ylim=c(-0.03,0.25), ylab = "score", pch=shpad)
tl;dr: problem is that if instead of the last line, I have plot(my.df$phase, my.df$val, type="p", ylim=c(-0.03,0.25), ylab = "score", pch=shpad, add=T), the formats are incongruent.
Alright, so, I've tried for a bit to accomplish what you wanted, but the best I could do with the base plotting system is this:
Which is accomplished purely by your lines of code above except for the last line, which I replaced with
points(my.df$phase,my.df$val,type="p",pch=shpad)
However, I think you can do much better, if you want to keep the same kind of plot, using the ggplot2 library. Using this code:
library('ggplot2')
new.df <- data.frame(avg,phase=levels(factor(phase)))
ggplot(new.df) +
geom_bar(stat="identity",aes(x=levels(phase),y=avg, fill=c("NsNm","NsLm","LsNm","LsLm")))+
geom_point(aes(x=my.df$phase,y=my.df$val,shape=factor(shpad))) +
scale_x_discrete(name="Type",labels=c("NsNm","NsLm","LsNm","LsLm")) +
ylab("Score")
you can make this chart:
I didn't adjust the coloring and the point types and the legend titles (not sure how important they are, but those can be fiddled with). However, you can see this probably produces the result you were aiming for.

R plotting a graph with different groups of data

I have a dataset:
a<-c(1,2,3,4,5,6,7,8,9,10)
b<-c(2,2,2,2,4,5,6,8,4,1)
c<-c("red","red","red","blue","blue","blue","orange","orange","orange","orange")
data<-data.frame(a=a,b=b,c=c)
I now want to plot the data on a graph with each group having a different colour:
plot(a[c=="red"],b[c=="red"],col="red",xlim=c(min(a),max(a)),ylim=c(min(b),max(b)))
points(a[c=="blue"],b[c=="blue"],col="blue")
points(a[c=="orange"],b[c=="orange"],col="orange")
This works fine - however, say if I have 30 groups, the task of writing the code becomes tedious. I am wondering if there is a better way of writing the code such that R will automatically plot the graph and give different colours to different groups?
Also, I wonder if there is a quick way to display a legend in the graph.
Thank you for all your help.
Try this:
with(data,plot(a,b,col=c))
The col argument in plot() stands for color. This can contain a vector of the colors you want.
Additionally, you don't have to make a column just to define the color if the color-group relationship is not that important. For example, you could make column c a more meaningful column like this:
a<-c(1,2,3,4,5,6,7,8,9,10)
b<-c(2,2,2,2,4,5,6,8,4,1)
c<-c(rep('Group1',3),rep('Group2',3),rep('Group3',4))
data<-data.frame(a=a,b=b,c=c)
Then to plot, use:
with(data,plot(a,b,col=c))
To add a legend:
legend('topleft',legend = levels(data[,'c']),col=1:nlevels(data[,'c']),pch=1)
Try ggplot2
library(ggplot2)
ggplot(data=data, aes(x=a, y=b, colour=c)) + geom_point()

Plotting content from multiple data frames into a single ggplot2 surface

I am a total R beginner here, with corresponding level of sophistication of this question.
I am using the ROCR package in R to generate plotting data for ROC curves. I then use ggplot2 to draw the plot. Something like this:
library(ggplot2)
library(ROCR)
inputFile <- read.csv("path/to/file", header=FALSE, sep=" ", colClasses=c('numeric','numeric'), col.names=c('score','label'))
predictions <- prediction(inputFile$score, inputFile$label)
auc <- performance(predictions, measure="auc")#y.values[[1]]
rocData <- performance(predictions, "tpr","fpr")
rocDataFrame <- data.frame(x=rocData#x.values[[1]],y=rocData#y.values[[1]])
rocr.plot <- ggplot(data=rd, aes(x=x, y=y)) + geom_path(size=1)
rocr.plot <- rocr.plot + geom_text(aes(x=1, y= 0, hjust=1, vjust=0, label=paste(sep = "", "AUC = ",round(auc,4))),colour="black",size=4)
This works well for drawing a single ROC curve. However, what I would like to do is read in a whole directory worth of input files - one file per classifier test results - and make a ggplot2 multifaceted plot of all the ROC curves, while still printing the AUC score into each plot.
I would like to understand what is the "proper" R-style approach to accomplishing this. I am sure I can hack something together by having one loop go through all files in the directory and create a separate data frame for each, and then having another loop to create multiple plots, and somehow getting ggplo2 to output all these plots onto the same surface. However, that does not let me use ggplot2's built-in faceting, which I believe is the right approach. I am not sure how to get my data into proper shape for faceting use, though. Should I be merging all my data frames into a single one, and giving each merged chunk a name (e.g. filename) and faceting on that? If so, is there a library or recommended practice for making this happen?
Your suggestions are appreciated. I am still wrapping my head around the best practices in R, so I'd rather get expert advice instead of just hacking things up to make code that looks more like ordinary declarative programming languages that I am used to.
EDIT: The thing I am least clear on is whether, when using ggplot2's built-in faceting capabilities, I'd still be able to output a custom string (AUC score) into each plot it will generate.
Here is an example of how to generate a plot as you described. I use the built-in dataset quakes:
The code does the following:
Load the ggplot2 and plyr packages
Add a facet variable to quakes - in this case I summarise by depth of earthquake
Use ddply to summarise the mean magnitude for each depth
Use ggplot with geom_text to label the mean magnitude
The code:
library(plyr)
library(ggplot2)
quakes$level <- cut(quakes$depth, 5,
labels=c("Very Shallow", "Shallow", "Medium", "Deep", "Very Deep"))
quakes.summary <- ddply(quakes, .(level), summarise, mag=round(mean(mag), 1))
ggplot(quakes, aes(x=long, y=lat)) +
geom_point(aes(colour=mag)) +
geom_text(aes(label=mag), data=quakes.summary, x=185, y=-35) +
facet_grid(~level) +
coord_map()

plot multiple line segments on one graph using R

How can I duplicate this style of graph, with multiple plots on one graph, and, preferably, legends attached as below.
I have tried the concept of "facet" but ggplot2 and trellis:xyplot both think of facets as separate panels rather than overlaid plots.
I can do it using plain Jane plot() and line().. but was using ggplot2 and woudl like to get multiple lines on one plot in that package.
Here is some example data in long form (captured from the plot using a nifty app called "Graphclick")
comp <- read.table(pipe("pbpaste"), header=T, sep=',')
company, year, sales
Apple,1975.003,17298.457
Apple,1977.302,16784.502
Apple,1978.314,17298.457
Apple,1980.246,20730.098
Apple,1981.533,27608.426
Apple,1984.293,40862.852
Apple,1986.408,50468.617
Apple,1987.328,48236.188
Apple,1988.892,35676.547
Apple,1989.904,34616.582
Apple,1991.192,44732.742
Apple,1992.387,44732.742
Apple,1993.399,39055.324
Apple,1995.791,37894.922
Apple,1996.895,39648.746
Apple,1998.274,52804.367
Apple,1999.378,61399.512
Apple,2001.770,2.350e5
Apple,2005.265,7.735e5
Toshiba,1999.378,86856.6
Toshiba,2001.862,1.192e5
Toshiba,2004.069,1.495e5
Toshiba,2004.069,1.495e5
IBM,1975.003,22019.092
IBM,1975.830,27195.193
IBM,1976.934,30682.320
IBM,1978.130,31148.527
IBM,1980.430,35676.547
IBM,1981.625,35676.547
IBM,1983.005,39648.746
IBM,1985.305,40862.852
IBM,1986.408,46102.508
IBM,1987.512,64241.156
IBM,1989.996,75832.898
IBM,1991.100,84276.039
IBM,1992.295,85556.641
IBM,1993.307,79342.539
IBM,1994.779,79342.539
IBM,1995.791,84276.039
IBM,1996.895,95082.484
IBM,1996.895,95082.484
Commodore,1975.003,33588.051
Commodore,1975.830,34616.582
Commodore,1977.118,25219.982
Commodore,1978.130,23388.229
Commodore,1979.326,25992.234
Commodore,1980.521,21689.514
Commodore,1981.717,25219.982
Commodore,1984.201,6999.029
Commodore,1985.213,1670.460
Commodore,1986.408,1458.447
(source: asymco.com)
If you're looking for the most control, you could just use the low-level plot and lines commands. Use "plot" to generate the first graph (with title, xlimits, and ylimits), then use "lines" to add lines to that graph.
plot(0,type="n", xlim=c(0,10), ylim=c(0,10), xlab="X Label", ylab="Y Label", main="Title")
Then add lines using the lines command:
lines(1:10, 1:10, type="l", lty=2)
lines(2:4, 10:8, col=2, type="l")
lines(6:9, c(5,6,5,6), col=3, type="l")
You can fine-tune the look by using all of the parameters listed in the "par" help file ("?par")
so, in ggplot2, this code works
qplot(year, sales, data=comp, colour=as.factor(company), group= company, geom="path", log="y")
The only things left now is to format the value on the Y axis as numeric (not sci notation), and the labels are in an off-graph legend, rather than on the plots... Final suggestions welcomed.
This is a lot easier in the end than plot() + lines(), as that required support code to get the ranges, iterate over the group levels etc.

Resources