As from the title suppose this vector and plot:
plot(rnorm(200,5,2),type="l")
This returns this plot
What i would like to know is whether there is a way to make the first half of it to be in blue col="blue" and the rest of it to be in red "col="red".
Similar question BUT in Matlab not R: Here
You could simply use lines for the second half:
dat <- rnorm(200, 5, 2)
plot(1:100, dat[1:100], col = "blue", type = "l", xlim = c(0, 200), ylim = c(min(dat), max(dat)))
lines(101:200, dat[101:200], col = "red")
Not a base R solution, but I think this is how to plot it using ggplot2. It is necessary to prepare a data frame to plot the data.
set.seed(1234)
vec <- rnorm(200,5,2)
dat <- data.frame(Value = vec)
dat$Group <- as.character(rep(c(1, 2), each = 100))
dat$Index <- 1:200
library(ggplot2)
ggplot(dat, aes(x = Index, y = Value)) +
geom_line(aes(color = Group)) +
scale_color_manual(values = c("blue", "red")) +
theme_classic()
We can also use the lattice package with the same data frame.
library(lattice)
xyplot(Value ~ Index, data = dat, type = 'l', groups = Group, col = c("blue", "red"))
Notice that the blue line and red line are disconnected. Not sure if this is important, but if you want to plot a continuous line, here is a workaround in ggplot2. The idea is to subset the data frame for the second half, plot the entire data frame with color as blue, and then plot the second data frame with color as red.
dat2 <- dat[dat$Index %in% 101:200, ]
ggplot(dat, aes(x = Index, y = Value)) +
geom_line(color = "blue") +
geom_line(data = dat2, aes(x = Index, y = Value), color = "red") +
theme_classic()
I'm struggling with ggplot (I always do). There are a number of very similar questions about forcing ggplot to include zero value categories in legends - here and here (for example). BUT I (think I) have a slightly different requirement to which all my mucking about with scale_x_discrete and scale_fill_manual has not helped.
Requirement: As you can see; the right-hand plot has no data in the TM=5 category - so is missing. What I need is for that right plot to have category 5 shown on the axis but obviously with no points or box.
Current Plot Script:
#data
plotData <- data.frame("TM" = c(3,2,3,3,3,4,3,2,3,3,4,3,4,3,2,3,2,2,3,2,3,3,3,2,3,1,3,2,2,4,4,3,2,3,4,2,3),
"Score" = c(5,4,4,4,3,5,5,5,5,5,5,3,5,5,4,4,5,4,5,4,5,4,5,4,4,4,4,4,5,4,4,5,3,5,5,5,5))
#vars
xTitle <- bquote("T"["M"])
v.I <- plotData$TM
depVar <- plotData$Score
#plot
p <- ggplot(plotData, aes_string(x=v.I,y=depVar,color=v.I)) +
geom_point() +
geom_jitter(alpha=0.8, position = position_jitter(width = 0.2, height = 0.2)) +
geom_boxplot(width=0.75,alpha=0.5,aes_string(group=v.I)) +
theme_bw() +
labs(x=xTitle) +
labs(y=NULL) +
theme(legend.position='none',
axis.text=element_text(size=10, face="bold"),
axis.title=element_text(size=16))
Attempted Solutions:
drop=False to scales (suggested by #Jarretinha here) totally borks margins and x-axis labels
> plot + scale_x_discrete(drop=FALSE) + scale_fill_manual(drop=FALSE)
Following logic from here and manually setting the labels in scale_fill_manual does nothing and results in the same right-hand plot from example above.
> p + scale_fill_manual(values = c("red", "blue", "green", "purple", "pink"),
labels = c("Cat1", "Cat2", "Cat3", "Cat4", "Cat5"),
drop=FALSE)
Playing with this logic and trying something with scale_x_discrete results in a change to category names on x-axis but the fifth is still missing AND the margins (as attempt 1) are borked again. BUT apparent that scale_x_discrete is important and NOT the whole answer
> p + scale_x_discrete(limits = c("Cat1", "Cat2", "Cat3", "Cat4", "Cat5"), drop=FALSE)
ANSWER for above example courtesy of input from #Bouncyball & #aosmith
#data
plotData <- data.frame("TM" = c(3,2,3,3,3,4,3,2,3,3,4,3,4,3,2,3,2,2,3,2,3,3,3,2,3,1,3,2,2,4,4,3,2,3,4,2,3),
"Score" = c(5,4,4,4,3,5,5,5,5,5,5,3,5,5,4,4,5,4,5,4,5,4,5,4,4,4,4,4,5,4,4,5,3,5,5,5,5))
plotData$TM <- factor(plotData$TM, levels=1:5) # add correct (desired number of factors to input data)
#vars
xTitle <- bquote("T"["M"])
v.I <- plotData$TM
depVar <- plotData$Score
myPalette <- c('#5c9bd4','#a5a5a4','#4770b6','#275f92','#646464','#002060')
#plot
ggplot(plotData, aes_string(x=v.I,y=depVar,color=v.I)) +
geom_jitter(alpha=0.8, position = position_jitter(width = 0.2, height = 0.2)) +
geom_boxplot(width=0.75,alpha=0.5,aes_string(group=v.I)) +
scale_colour_manual(values = myPalette, drop=F) + # new line added here
scale_x_discrete(drop=F) + # new line added here
theme_bw() +
labs(x=xTitle) +
labs(y=NULL) +
theme(legend.position='none',
axis.text=element_text(size=10, face="bold"),
axis.title=element_text(size=16))
Here's a workaround you could use:
# generate dummy data
set.seed(123)
df1 <- data.frame(lets = sample(letters[1:4], 20, replace = T),
y = rnorm(20), stringsAsFactors = FALSE)
# define factor, including the missing category as a level
df1$lets <- factor(df1$lets, levels = letters[1:5])
# make plot
ggplot(df1, aes(x = lets, y = y))+
geom_boxplot(aes(fill = lets))+
geom_point(data = NULL, aes(x = 'e', y = 0), pch = NA)+
scale_fill_brewer(drop = F, palette = 'Set1')+
theme_bw()
Basically, we plot an "empty" point (i.e. pch = NA) so that the category shows up on the x-axis, but has no visible geom associated with it. We also define our discrete variable, lets as a factor with five levels when only four are present in the data.frame. The missing category is the letter e.
NB: You'll have to adjust the positioning of this "empty" point so that it doesn't skew your y axis.
Otherwise, you could use the result from this answer to avoid having to plot an "empty" point.
# generate dummy data
set.seed(123)
df1 <- data.frame(lets = sample(letters[1:4], 20, replace = T),
y = rnorm(20), stringsAsFactors = FALSE)
# define factor, including the missing category as a level
df1$lets <- factor(df1$lets, levels = letters[1:5])
# make plot
ggplot(df1, aes(x = lets, y = y)) +
geom_boxplot(aes(fill = lets)) +
scale_x_discrete(drop = F) +
scale_fill_brewer(drop = F, palette = 'Set1') +
theme_bw()
I have this dataset: https://dl.dropboxusercontent.com/u/73950/data.csv
The dataset contains 3 variables.
Here's how I visualize the data right now:
library(ggplot2)
library(reshape2)
library(RColorBrewer)
dat = read.csv("data.csv", header = FALSE)
myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")))
sc <- scale_colour_gradientn(colours = myPalette(100))
ggplot(dat, aes(x=V1, y=V3, colour = V2))+ geom_point(alpha = .2,size = 3) + sc
Instead of just one figure, I'd like to facet the figure to display 3 different ways to attribute variables to each axis and color. As such:
x = V1, y = V2, color = V3
x = V1, y = V3, color = V2
x = V2, y = V3, color = V1
How to do this kind of things with ggplot2's faceting?
You can get this by putting the data in the format ggplot likes. In this case, a column that can be used to split the data into facets (called var below). To do that, I just repeated the data three times, choosing the appropriate x and y variables for each 2-way combo, and using the variable left out of each combination as the coloring variable.
## Rearrange the data by 2-way combinations, the coloring is the remaining column
res <- do.call(rbind, combn(1:3, 2, function(ii)
cbind(setNames(dat[,c(ii, setdiff(1:3, ii))], c("x", "y", "color")),
var=paste(ii, collapse=".")), simplify=F))
ggplot(res, aes(x=x, y=y, color=color))+ geom_point(alpha = .2,size = 3) +
facet_wrap(~ var, scales="free") + sc
Is it possible to split the fill legend of a ggplot barplot following the values on the x-axis of the plot?
For example using this data:
library(ggplot2)
data <- data.frame(val=c(2,4,5,6,7,8,9),var1=c("A","A","A","B","B","C","C"),
var2=sample(LETTERS[1:7]))
ggplot(data,aes(x=factor(var1),y=val,fill=var2))+geom_bar(stat="identity")
I get the following plot:
I would like to have something like this to make it easier to find what each fill color corresponds to:
An alternative to the solutions in the links in the comments. The solution assumes that the data is available in an aggregated form, and that each category of var2 appear in one and only one category of var1. That is, the number of keys (and their order) in the legend is correct. All that need happen is for space to be inserted between appropriate keys and text dropped into those spaces. It gets the information it needs to construct the plot from the initial plot or its build data.
library(ggplot2)
library(gtable)
library(grid)
set.seed(1234)
data <- data.frame(val = c(2,4,5,6,7,8,9),
var1 = c("A","A","A","B","B","C","C"),
var2 = sample(LETTERS[1:7]))
# Sort levels of var2
data$var2 = factor(data$var2, labels = data$var2, levels = data$var2)
p = ggplot(data, aes(x = factor(var1), y = val, fill = var2)) +
geom_bar(stat = "identity")
# Get the ggplot grob
g = ggplotGrob(p)
# Get the legend
leg = g$grobs[[which(g$layout$name == "guide-box")]]$grobs[[1]]
# Get the labels from the ggplot build data
gt = ggplot_build(p)
labels = rev(gt$layout$panel_params[[1]]$x.labels)
## Positions of the labels
# Get the number of keys within each label from the ggplot build data
gt$data[[1]]$x
N = as.vector(table(gt$data[[1]]$x))
N = N[-length(N)]
# Get the positions of the labels in the legend gtable
pos = rev(cumsum(N)) + 3
pos = c(pos, 3)
# Add rows to the legend gtable, and add the labels to the new rows
for(i in seq_along(pos)){
leg = gtable_add_rows(leg, unit(1.5, "lines"), pos = pos[i])
leg = gtable_add_grob(leg, textGrob(labels[i], y = 0.1, just = "bottom"),
t = pos[i] + 1, l = 2)
}
# Put the legend back into the plot
g$grobs[[which(g$layout$name == "guide-box")]]$grobs[[1]] = leg
# Draw it
grid.newpage()
grid.draw(g)
I am very new to R and ggplot2. I am trying to create a grid of plots of correlations as well as their trailing max and min values using a for loop. The plots are then saved as a PDF to a directory. When they are saved the blue lines(min max) are correctly plotted. However when I then use the do.call(grid.arrange,t) or any other call to the plots in the list. you do not get the correct blue lines, but the last plots blue lines populate all of the plots.
I dont understand how this can plot and save the pdf correctly but not store the ggplot object correctly in the t list() or how there is some confusion in the render using do.call(grid.arrange,t). How can the original line (black) plot correctly but the geom_line additions do not ? I am really confused.
If someone could kindly help me check this code and find out how to plot all lines correctly then place them in a grid that would be great.
reproducable code below using random data
require(TTR)
require(ggplot2)
library(gridExtra)
set.seed(12345)
filelocation = "c:/"
values <- as.data.frame(matrix( rnorm(5*500,mean=0,sd=3), 500, 5))
t <- list()
rollLength = 25
for( i in 1:(ncol(values)))
{
p <- ggplot(data=values, aes(x = index(values)) )
p <- p + geom_line(data=values, aes_string(y = colnames(values)[i]))
p <- p + geom_line(data = values, aes(x = index(values), y = runMax(values[,i], n = rollLength) ), colour = "blue", linetype = "longdash" )
p <- p + geom_line(data = values, aes(x = index(values), y = runMin(values[,i], n = rollLength) ), colour = "blue", linetype = "longdash" )
p <- p + ggtitle(colnames(values)[i]) + xlab("Date") + ylab("Pearson Correlation")
print(p)
ggsave( file = paste(colnames(values)[i],".pdf",sep = "") , path = filelocation)
assign(paste("p", i, sep = ""), p)
t[[i]] <- p
}
do.call(grid.arrange,t)
Hmm, this isn't exactly what you want I think, but close, and less code
require(TTR)
require(ggplot2)
set.seed(12345)
values <- as.data.frame(matrix( rnorm(5*500,mean=0,sd=3), 500, 5))
rollLength = 25
library(reshape2)
dfmelt <- melt(values)
dfmelt$max <- runMax(dfmelt$value, n=rollLength)
dfmelt$min <- runMin(dfmelt$value, n=rollLength)
dfmelt$row <- index(dfmelt)
ggplot(dfmelt, aes(x = row, y = value)) +
geom_line() +
geom_line(aes(x = row, y = max), data=dfmelt, colour = "blue",
linetype = "longdash") +
geom_line(aes(x = row, y = min), data=dfmelt, colour = "blue",
linetype = "longdash") +
facet_wrap(~ variable, scales="free")