Change point shape in gig-lot only for certain observations - r

I'm plotting a graph in R using ggplot2. It's a lined graph with points for every observations, the points represent p-values. Three of them are not significant, and I want these points to show up differently (any other shape/color, doesn't matter). Now I'm not sure how to do this.
I've tried scale_shape_manual(values = c(valueA, valueB, valueC)) and
scale_color_manual, but I don't get any results. No error messages either, just nothing happens.
Can anyone help?
ggplot(data = dataframe) +
geom_line(aes(x=Time, y=Treatment), color="#00AFBB")+
geom_point(aes(x=Time, y=Treatment)) +
scale_y_reverse()+
scale_x_continuous( breaks = c(1, 2, 3, 4, 5, 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20))
Thanks!
--
Edit: here a reproducible sample (I hope it works?):
A <- c(1,2,3,4,5)
B <- c(1,2,3,4,5)
df <- data.frame(cbind(A, B))

Here's an example, hopefully helpful. I use scale_color_identity and scale_shape_identity because my data (in this case created through the if_else statements) specifies the literal color/shape I want to use.
Time <- c(1,2,3,4,5)
Treatment <- c(1,2,3,4,5)
df <- data.frame(Time = 1:5, Treatment = 1:5)
ggplot(data = df) +
geom_line(aes(x=Time, y=Treatment), color = "#00AFBB") +
geom_point(aes(x=Time, y=Treatment,
shape = if_else(Treatment < 5, 18, 1),
color = if_else(Treatment < 5, "#00AFBB", "black")), size = 4) +
scale_y_reverse()+
scale_x_continuous( breaks = 1:20) +
scale_color_identity() +
scale_shape_identity()

Related

breaks at integer powers of ten on ggplot2 log10 axes

Transforming ggplot2 axes to log10 using scales::trans_breaks() can sometimes (if the range is small enough) produce un-pretty breaks, at non-integer powers of ten.
Is there a general purpose way of setting these breaks to occur only at 10^x, where x are all integers, and, ideally, consecutive (e.g. 10^1, 10^2, 10^3)?
Here's an example of what I mean.
library(ggplot2)
# dummy data
df <- data.frame(fct = rep(c("A", "B", "C"), each = 3),
x = rep(1:3, 3),
y = 10^seq(from = -4, to = 1, length.out = 9))
p <- ggplot(df, aes(x, y)) +
geom_point() +
facet_wrap(~ fct, scales = "free_y") # faceted to try and emphasise that it's general purpose, rather than specific to a particular axis range
The unwanted result -- y-axis breaks are at non-integer powers of ten (e.g. 10^2.8)
p + scale_y_log10(
breaks = scales::trans_breaks("log10", function(x) 10^x),
labels = scales::trans_format("log10", scales::math_format(10^.x))
)
I can achieve the desired result for this particular example by adjusting the n argument to scales::trans_breaks(), as below. But this is not a general purpose solution, of the kind that could be applied without needing to adjust anything on a case-by-case basis.
p + scale_y_log10(
breaks = scales::trans_breaks("log10", function(x) 10^x, n = 1),
labels = scales::trans_format("log10", scales::math_format(10^.x))
)
Should add that I'm not wed to using scales::trans_breaks(), it's just that I've found it's the function that gets me closest to what I'm after.
Any help would be much appreciated, thank you!
Here is an approach that at the core has the following function.
breaks = function(x) {
brks <- extended_breaks(Q = c(1, 5))(log10(x))
10^(brks[brks %% 1 == 0])
}
It gives extended_breaks() a narrow set of 'nice numbers' and then filters out non-integers.
This gives us the following for you example case:
library(ggplot2)
library(scales)
#> Warning: package 'scales' was built under R version 4.0.3
# dummy data
df <- data.frame(fct = rep(c("A", "B", "C"), each = 3),
x = rep(1:3, 3),
y = 10^seq(from = -4, to = 1, length.out = 9))
ggplot(df, aes(x, y)) +
geom_point() +
facet_wrap(~ fct, scales = "free_y") +
scale_y_continuous(
trans = "log10",
breaks = function(x) {
brks <- extended_breaks(Q = c(1, 5))(log10(x))
10^(brks[brks %% 1 == 0])
},
labels = math_format(format = log10)
)
Created on 2021-01-19 by the reprex package (v0.3.0)
I haven't tested this on many other ranges that might be difficult, but it should generalise better than setting the number of desired breaks to 1. Difficult ranges might be those just in between -but not including- powers of 10. For example 11-99 or 101-999.

Plot unsimilar data with ggplot

I am trying to plot the different lines, but one of the observations is far more beyond the normal scale.
library(ggplot2)
library(reshape)
library(dplyr)
a = matrix(rnorm(50, 0, 1), ncol=5)
b = c(rnorm(5, 0, 2), rnorm(5,20,2))
dt = data.frame(a,b)
rownames(dt) = paste0('Day',1:10)
colnames(dt) = c('A','B','C','D','E','F')
mdt = melt(as.matrix(dt), varnames=c('Date', 'Model'))
head(mdt)
ggplot(mdt, aes(x=Date, y=value, group=Model, color=Model))+
geom_line(size=1.2)
This is what I got:
As you can see, the large fluctuation of F enlarges my general y axis scale and makes the other five observations' trends unclear.
I tried to set the ylim=(-5,5), then I lost the entire F:
I am not entirely sure how shall I plot all of them together, but I am thinking is it possible to scale the out of range part, like the following part, or you actually wouldn't recommend this?
Any advice is highly appreciated. Thanks!
I don't know if this is the best option for you data, but you can divide each group by it's range to make it more like a ratio.
library(data.table)
library(ggplot2)
set.seed(99)
dt <- data.table(value = c(rnorm(10, 0, 5), rnorm(20)),
cat = rep(c("x", "y", "z"), each = 10),
id = rep(1:10, 3))
ggplot(dt, aes(id, value, color = cat)) +
geom_line(size = 2)
ggplot(dt[, ratio := value / diff(range(value)), cat], aes(id, ratio, color = cat)) +
geom_line(size = 2)

ggplot2 geom_line indicating group size

Following http://docs.ggplot2.org/current/aes_group_order.html
h <- ggplot(Oxboys, aes(age, height))
h + geom_line(aes(group = Subject))
Produces
But if two Subjects have exactly the same line, one subject's line will hide the other. Could we use line thickness or intensity to indicate the number of subjects who have the same line? Could we add a bubble using geom_point() to indicate the number of subjects?
Use geom_line(aes(group = 'Subject'), alpha = .5). Play around with the alpha values.
You could accomplish it by first mapping the colour and size aesthetics and then adjusting their values using the scale_size_manual and scale_colour_manual functions. Below is a demonstration of the approach.
# a fake data set with two pairs of identical lines:
df <- data.frame(t = c(1:10, 1:10, 1:10, 1:10),
a = c(1:10, 1:10, seq(5, 8, length =10), seq(5, 8, length =10)),
c = rep(c("a", "b", "c", "d"), each = 10))
ggplot(df, aes(x = t, y = a, group = c)) +
geom_line(aes(size = c, colour = c)) +
scale_size_manual(values = c(4, 2, 3, 1.5)) +
scale_colour_manual(values = c("black", "red", "blue", "yellow"))
You must consider how your grouping factor (in the example c) is ordered, because the lines are also plotted in this order. So the line which is plotted first should get a larger value for size.

Recursive indexing error with facet wrap

I have two graphics side-by-side using facet_wrap and want to do the following things:
draw a square, but a different square in each facet
draw a vertical line, but a vertical line in a different location in each facet
I used this link to accomplish #1, but I can't do #2 in combination with that
ggplot2 - create different geom_path objects in facets
I created the following data frames
square1 = data.frame(x=c(.....),y=c(.....),z=a)
square2 = data.frame(x=c(.....),y=c(.....),z=b)
df1 = rbind(square1,square2) # 10*3 data frame that defines the dimensions of the squares to draw with z taking value of a or b
df2 = data.frame(x=c(..),z=c(a,b)) # 2*2 data frame with z taking value of a or b
The below code sets up the facets and all works fine:
RE <- ggplot(data, aes())
RE <- RE + geom_point(aes())
RE <- RE + xlab() + ylab() + ggtitle()
RE <- RE + coord_cartesian()
RE <- RE + scale_colour_brewer()
RE <- RE + theme_bw()
RE <- facet_wrap(~ v1 + v2, ncol=2)
But running this code results in the following error:
RE <- RE + geom_path(aes(x = x, y = y), data = df1)
RE <- RE + geom_vline(aes(xintercept = x), data = df2)
Error in panel$x_scales[[this_panel$SCALE_X]] : recursive indexing
failed at level 4
Note that I can run one or the other lines of code but not both.
You have not provided any data so I have created some data following the pattern you provided in your earlier post. Note that the data frame contains x and y coordinates for the points and the paths; a variable facet to tell ggplot in which panel to draw the points and paths; and a variable vline which gives the location of the vertical lines (in the v1 panel, the vline intercept is at x=2; in the v2 panel, the vline intercept is at x=3).
library(ggplot2)
square1 <- data.frame(x = c(1, 5, 5, 1, 1),
y = c(1, 1, 5, 5, 1),
facet = "v1",
vline = 2)
square2 <- data.frame(x = c(2, 4, 4, 2, 2),
y = c(2, 2, 4, 4, 2),
facet = "v2",
vline = 3)
df1 = rbind(square1,square2)
df1
ggplot(df1, aes(x, y)) +
geom_point(colour = "red", size = 5) +
geom_path(colour = "red", size = 2) +
geom_vline(aes(xintercept = vline),colour = "blue", size = 2) +
theme_bw() +
facet_wrap(~ facet, ncol=2)

How to add ggplot legend of two different lines R?

I need to add a legend of the two lines (best fit line and 45 degree line) on TOP of my two plots. Sorry I don't know how to add plots! Please please please help me, I really appreciate it!!!!
Here is an example
type=factor(rep(c("A","B","C"),5))
xvariable=seq(1,15)
yvariable=2*xvariable+rnorm(15,0,2)
newdata=data.frame(type,xvariable,yvariable)
p = ggplot(newdata,aes(x=xvariable,y=yvariable))
p+geom_point(size=3)+ facet_wrap(~ type) +
geom_abline(intercept =0, slope =1,color="red",size=1)+
stat_smooth(method="lm", se=FALSE,size=1)
Here is another approach which uses aesthetic mapping to string constants to identify different groups and create a legend.
First an alternate way to create your test data (and naming it DF instead of newdata)
DF <- data.frame(type = factor(rep(c("A", "B", "C"), 5)),
xvariable = 1:15,
yvariable = 2 * (1:15) + rnorm(15, 0, 2))
Now the ggplot code. Note that for both geom_abline and stat_smooth, the colour is set inside and aes call which means each of the two values used will be mapped to a different color and a guide (legend) will be created for that mapping.
ggplot(DF, aes(x = xvariable, y = yvariable)) +
geom_point(size = 3) +
geom_abline(aes(colour="one-to-one"), intercept =0, slope = 1, size = 1) +
stat_smooth(aes(colour="best fit"), method = "lm", se = FALSE, size = 1) +
facet_wrap(~ type) +
scale_colour_discrete("")
Try this:
# original data
type <- factor(rep(c("A", "B", "C"), 5))
x <- 1:15
y <- 2 * x + rnorm(15, 0, 2)
df <- data.frame(type, x, y)
# create a copy of original data, but set y = x
# this data will be used for the one-to-one line
df2 <- data.frame(type, x, y = x)
# bind original and 'one-to-one data' together
df3 <- rbind.data.frame(df, df2)
# create a grouping variable to separate stat_smoothers based on original and one-to-one data
df3$grp <- as.factor(rep(1:2, each = nrow(df)))
# plot
# use original data for points
# use 'double data' for abline and one-to-one line, set colours by group
ggplot(df, aes(x = x, y = y)) +
geom_point(size = 3) +
facet_wrap(~ type) +
stat_smooth(data = df3, aes(colour = grp), method = "lm", se = FALSE, size = 1) +
scale_colour_manual(values = c("red","blue"),
labels = c("abline", "one-to-one"),
name = "") +
theme(legend.position = "top")
# If you rather want to stack the two keys in the legend you can add:
# guide = guide_legend(direction = "vertical")
#...as argument in scale_colour_manual
Please note that this solution does not extrapolate the one-to-one line outside the range of your data, which seemed to be the case for the original geom_abline.

Resources