How can I plot multiple variables side-by-side in a dotplot in R? - r

I'm still pretty new to R, and have come up against a plotting problem I can't find an answer to.
I've got a data frame that looks like this (though a lot bigger):
df <- data.frame(Treatment= rep(c("A", "B", "C"), each = 6),
LocA=sample(1:100, 18),
LocB=sample(1:100, 18),
LocC=sample(1:100, 18))
And I want dot plots that look like this one produced in Excel. It's exactly the formatting I want: a dotplot for each of the treatments side-by-side for each location, with data for multiple locations together on one graph. (Profuse apologies for not being able to post the image here; posting images requires a 10 reputation.)
It's no problem to make a plot for each location, with the dots color-coded, and so on:
ggplot(data = df, aes(x=Treatment, y=LocA, color = Treatment)) + geom_point()
but I can't figure out how to add locations B and C to the same graph.
Any advice would be much appreciated!

As a couple of people have mentioned, you need to "melt" the data, getting it into a "long" form.
library(reshape2)
df_melted <- melt(df, id.vars=c("Treatment"))
colnames(df_melted)[2] <- "Location"
In ggplot jargon, having different groups like treatment side-by-side is achieved through "dodging". Usually for things like barplots you can just say position="dodge" but geom_point seems to require a bit more manual specification:
ggplot(data=df_melted, aes(x=Location, y=value, color=Treatment)) +
geom_point(position=position_dodge(width=0.3))

You need to reshape the data. Here an example using reshape2
library(reshape2)
dat.m <- melt(dat, id.vars='Treatment')
library(ggplot2)
ggplot(data = dat.m,
aes(x=Treatment, y=value,shape = Treatment,color=Treatment)) +
geom_point()+facet_grid(~variable)
Since you want a dotplot, I propose also a lattice solution. I think it is more suitable in this case.
dotplot(value~Treatment|variable,
groups = Treatment, data=dat.m,
pch=c(25,19),
par.strip.text=list(cex=3),
cex=2)

Related

Multiple line plot using ggplot2

I am trying to emulate a ggplot of multiple lines which works as follows:
set.seed(45)
df <- data.frame(x=c(1,2,3,4,5,1,2,3,4,5,3,4,5), val=sample(1:100, 13),
variable=rep(paste0("category", 1:3), times=c(5,5,3)))
ggplot(data = df, aes(x=x, y=val)) + geom_line(aes(colour=variable))
I can get this simple example to work, however on a much larger data set I am following the same steps but it is not working.
ncurrencies = 6
dates = c(BTC$Date, BCH$Date, LTC$Date, ETH$Date, XRP$Date, XVG$Date)
opens = c(BTC$Open, BCH$Open, LTC$Open, ETH$Open, XRP$Open, XVG$Open)
categories = rep(paste0("categories", 1:ncurrencies),
times=c(nrow(BTC), nrow(BCH), nrow(LTC), nrow(ETH), nrowXRP), nrow(XVG)))
df = data.frame(dates, opens, categories)
# Plot - Not correct.
ggplot(data=df, aes(x=dates, y=opens)) +
geom_line(aes(colour=categories))
As you can see, the different points are discretised and the y-axis is strange. I am guessing this is a rookie error but I have been going round in circles for a while. Can anyone see it?
P.S. I don't think I can upload the data here as it would be too much code. However, the dataframe is in the same format as the practice example and the categories match up correctly to the x and y data. Therefore I believe it is the way I am defining ggplot - I am relatively new to R.
Thank you Markus and Jan, yes you are correct. df$opens was a factor and changing it to a numeric solved the problem.
opens = as.numeric(c(BTC$Open, BCH$Open, LTC$Open, ETH$Open, XRP$Open, XVG$Open))

Manually added legend not working in ggplot2?

Here's facsimile of my data:
d1 <- data.frame(
e=rnorm(3000,10,10)
)
d2 <- data.frame(
e=rnorm(2000,30,30)
)
So, I got around the problem of plotting two different density distributions from two very different datasets on the same graph by doing this:
ggplot() +
geom_density(aes(x=e),fill="red",data=d1) +
geom_density(aes(x=e),fill="blue",data=d2)
But when I try to manually add a legend, like so:
ggplot() +
geom_density(aes(x=e),fill="red",data=d1) +
geom_density(aes(x=e),fill="blue",data=d2) +
scale_fill_manual(name="Data", values = c("XXXXX" = "red","YYYYY" = "blue"))
Nothing happens. Does anybody know what's going wrong? I thought I could actually manually add legends if need be.
Generally ggplot works best when your data is in a single data.frame and in long format. In your case we therefore want to combine the data from both data.frames. For this simple example, we just concatenate the data into a long variable called d and use an additional column id to indicate to which dataset that value belongs.
d.f <- data.frame(id = rep(c("XXXXX", "YYYYY"), c(3000, 2000)),
d = c(d1$e, d2$e))
More complex data manipulations can be done using packages such as reshape2 and tidyr. I find this cheat sheet often useful. Then when we plot we map fill to id, and ggplot will take of the legend automatically.
ggplot(d.f, aes(x = d, fill = id)) +
geom_density()

overlaying 2 plots from different sized dataset with legends using ggplot

I have 2 datasets, with different size. How do I simply plot them and have each with a different color and a legend?
So in this case, the legend would be count1, count2, and the legend title is something I choose, let's say: mylegend. What do I need to change or add to the following commands?
x <- data.frame(Q=1:10, count1=21:30)
y <- data.frame(Q=seq(1,10,0.5), count2=seq(11,20, 0.5))
ggplot() + geom_line(data=x, aes(x=Q, y=count1)) + geom_point(data=y, aes(x=Q, y=count2))
The easiest solution is to combine your data in the same data.frame, then set the aesthetics (aes) in ggplot.
Here is one way you can combine everything:
df <- data.frame(Q = c(x$Q, y$Q),
count = c(x$count1, y$count2),
type = c(rep("count1", 10), rep("count2", 19))
)
But you can also use commands like rbind() or melt() (from the reshape2 library).
With the data combined into one data.frame:
ggplot(df, aes(x=Q, y=count, colour=type)) + geom_point() + geom_line() +
scale_colour_discrete(name="mylegend")
This is a basic example, and I highly recommend Hadley Wickham's ggplot2 book, as well just searching google (Stack Overflow, R Cookbook, etc) for solutions to specific plotting problems or more ways to customize your plots.

ggplot2: how to overlay 2 plots when using stat_summary

i am totally new in R so maybe the answer to the question is trivial but I couldn't find any solution after searching in the net for days.
I am using ggplot2 to create graphs containing the mean of my samples with the confidence interval in a ribbon (I can't post the pic but something like this: S1
I have a data frame (df) with time in the first column and the values of the variable measured in the other columns (each column is a replicate of the measurement).
I do the following:
mdf<-melt(df, id='time', variable_name="samples")
p <- ggplot(data=mdf, aes(x=time, y=value)) +
geom_point(size=1,colour="red")
stat_sum_df <- function(fun, geom="crosbar", ...) {
stat_summary(fun.data=fun, geom=geom, colour="red")
}
p + stat_sum_df("mean_cl_normal", geom = "smooth")
and I get the graph I have shown at the beginning.
My question is: if I have two different data frames, each one with a different variable, measured in the same sample at the same time, how I can plot the 2 graphs in the same plot? Everything I have tried ends in doing the statistics in the both sets of data or just in one of them but not in both. Is it possible just to overlay the plots?
And a second small question: is it possible to change the colour of the ribbon?
Thanks!
something like this:
library(ggplot2)
a <- data.frame(x=rep(c(1,2,3,5,7,10,15,20), 5),
y=rnorm(40, sd=2) + rep(c(4,3.5,3,2.5,2,1.5,1,0.5), 5),
g = rep(c('a', 'b'), each = 20))
ggplot(a, aes(x=x,y=y, group = g, colour = g)) +
geom_point(aes(colour = g)) +
geom_smooth(aes(fill = g))
I'd suggest you reading the basics of ggplot. Check ?ggplot2 for help on ggplot but also available help topics here and particularly how group aesthetic may be manipulated.
You'll find useful the discussion group at Google groups and maybe join it. Also, QuickR have a lot of examples on ggplot graphs and, obviously, here at Stackoverflow.

R: Plot multiple box plots using columns from data frame

I would like to plot an INDIVIDUAL box plot for each unrelated column in a data frame. I thought I was on the right track with boxplot.matrix from the sfsmsic package, but it seems to do the same as boxplot(as.matrix(plotdata) which is to plot everything in a shared boxplot with a shared scale on the axis. I want (say) 5 individual plots.
I could do this by hand like:
par(mfrow=c(2,2))
boxplot(data$var1
boxplot(data$var2)
boxplot(data$var3)
boxplot(data$var4)
But there must be a way to use the data frame columns?
EDIT: I used iterations, see my answer.
You could use the reshape package to simplify things
data <- data.frame(v1=rnorm(100),v2=rnorm(100),v3=rnorm(100), v4=rnorm(100))
library(reshape)
meltData <- melt(data)
boxplot(data=meltData, value~variable)
or even then use ggplot2 package to make things nicer
library(ggplot2)
p <- ggplot(meltData, aes(factor(variable), value))
p + geom_boxplot() + facet_wrap(~variable, scale="free")
From ?boxplot we see that we have the option to pass multiple vectors of data as elements of a list, and we will get multiple boxplots, one for each vector in our list.
So all we need to do is convert the columns of our matrix to a list:
m <- matrix(1:25,5,5)
boxplot(x = as.list(as.data.frame(m)))
If you really want separate panels each with a single boxplot (although, frankly, I don't see why you would want to do that), I would instead turn to ggplot and faceting:
m1 <- melt(as.data.frame(m))
library(ggplot2)
ggplot(m1,aes(x = variable,y = value)) + facet_wrap(~variable) + geom_boxplot()
I used iteration to do this. I think perhaps I wasn't clear in the original question. Thanks for the responses none the less.
par(mfrow=c(2,5))
for (i in 1:length(plotdata)) {
boxplot(plotdata[,i], main=names(plotdata[i]), type="l")
}

Resources