I'd like the x-axis of my barchart to be a continuous scale.
Here is my data:
list(
Century = c(1, 2, 3, 4, 5),
CenturyLabel = c("1st", "Bit later", "", "", "Post-Roman"),
Value = c(.2, .3, 0, 0, .4) ) %>% as_tibble()
I'm hoping to see bars for the 1st, 2nd, and 5th centuries with gaps for the 3rd and 4th.
The trick is to define your x-axis variable as a factor.
library("dplyr")
df <- tibble(
Century = c(1, 2, 3, 4, 5),
CenturyLabel = c("1st", "Bit later", "", "", "Post-Roman"),
Value = c(.2, .3, 0, 0, .4) )
df$CenturyFactor <- factor(df$Century, labels = df$CenturyLabel), ordered = TRUE)
You can then use CenturyFactor as x-axis variable and you'll see a gap with any correct plotting libraries... With the big caveat that any duplicate labels cause the centuries to be merged!
One way around this is to plot Century (1 to 5) but tweak the labels to show CenturyLabel. This will be library-specific. No factors needed.
Using ggplot2:
library("ggplot2")
ggplot(df, aes(x = Century, y = Value)) +
geom_col() +
scale_x_continuous(labels = df$CenturyLabel, breaks = df$Century)
Related
I'm trying to create a ggplot bar chart, and to create different colored fills for some bars.
I copied from somewhere the code, but with my data it just deosnt work.
Here is the code:
df <- data.frame(cat = c( 0, 1, 2, 3, 4),
perc = c(10, 20, 30, 40, 0),
mark = c( 0, 0, 0, 1, 0))
library(ggplot2)
ggplot(df) +
aes(x = cat, fill = mark, weight = perc) +
geom_bar()
But the result is a colorless chart, with this warning message:
The following aesthetics were dropped during statistical transformation: fill
ℹ This can happen when ggplot fails to infer the correct grouping structure in the data.
ℹ Did you forget to specify a `group` aesthetic or to convert a numerical variable into a factor?
What am I doing wrong?
The issue is that geom_bar uses stat_count by default, so it simply counts up the number of rows at each value of cat. This summary doesn't know what to do with the fill = mark part of your mapping, since there could be multiple values for mark in each category. In your case this isn't obvious because there is only one value for fill at each value of cat, but the same principle applies; if you are using a grouped summary function then you cannot have a row-wise fill variable.
My guess is that you are looking for geom_col
df <- data.frame(cat = c( 0, 1, 2, 3, 4),
perc = c(10, 20, 30, 40, 0),
mark = c( 0, 0, 0, 1, 0))
library(ggplot2)
ggplot(df) +
aes(x = cat, fill = mark, y = perc) +
geom_col()
Created on 2022-11-24 with reprex v2.0.2
I am trying to plot rectangles in the x-axis for different classes in the y-axis. I want to do this with geom_rect, but I don't want to use y_min and y_max since I want these to be determined by the classes (i.e. factors) I have in my data.
I managed to get the plot I want changing the breaks and the tick labels manually, but I am sure there must be a better way to do this.
Small toy example:
data <- data.frame(x_start = c(0, 2, 4, 6),
x_end = c(1, 3, 5, 7),
y_start = c(0, 0, 2, 2),
y_end = c(1, 1, 3, 3),
info = c("x", "x", "y", "y"))
Original plot:
ggplot(data ,aes(xmin=x_start, xmax=x_end, ymin=y_start, ymax=y_end, fill=info)) + geom_rect()
Plot that I want:
ggplot(data ,aes(xmin=x_start, xmax=x_end, ymin=y_start, ymax=y_end, fill=info)) + geom_rect() +
scale_y_continuous(breaks = c(0.5,2.5), labels = c("x","y"))
library(dplyr)
y_lab <- data %>%
distinct(y_end, y_start, info) %>%
mutate(y_mid = (y_end + y_start)/2)
ggplot(data, aes(xmin=x_start, xmax=x_end, ymin=y_start, ymax=y_end, fill=info)) +
geom_rect() +
scale_y_continuous(breaks = y_lab$y_mid, labels = y_lab$info)
Or using geom_tile:
ggplot(data, aes(x = (x_start + x_end)/2, y = info, fill=info, width = 1)) +
geom_tile()
I'm trying to visualize some data that looks like this
line1 <- data.frame(x = c(4, 24), y = c(0, -0.42864), group = "group1")
line2 <- data.frame(x = c(4, 12 ,24), y = c(0, 2.04538, 3.4135), group = "group2")
line3 <- data.frame(x = c(4, 12, 24), y = c(0, 3.14633, 3.93718), group = "group3")
line4 <- data.frame(x = c(0, 3, 7, 12, 18), y = c(0, -0.50249, 0.11994, -0.68694, -0.98949), group = "group4")
line5 <- data.frame(x = c(0, 3, 7, 12, 18, 24), y = c(0, -0.55753, -0.66006, 0.43796, 1.38723, 3.17906), group = "group5")
df <- do.call(rbind, list(line1, line2, line3, line4, line5))
What I'm trying to do is plot the least squares line (and points) for each group on the same plot. And I'd like the colour of the lines and points to correspond to the group.
All I've been able to do is plot the points according to their group
ggplot(data = df, aes(x, y, colour = group)) + geom_point(aes(size = 10))
But I have no idea how to add in the lines as well and make their colours correspond to the points that they are fitting.
I'd really appreciate any help with this. It's turning out to be so much harder than I though it would be.
You can simply add a geom_smooth layer to your plot
ggplot(data = df, aes(x, y, colour = group)) + geom_point(aes(size = 10)) +
geom_smooth(method="lm",se=FALSE)
method="lm" specifies that you want a linear model
se=FALSE to avoid plotting confidence intervals
I'm trying to create a line graph depicting different trajectories over time for two groups/conditions. I have two groups for which the data 'eat' was collected at five time points (1,2,3,4,5).
I'd like the lines to connect the mean point for each group at each of five time points, so I'd have two points at Time 1, two points at Time 2, and so on.
Here's a reproducible example:
#Example data
library(tidyverse)
library(ggplot2)
eat <- sample(1:7, size = 30, replace = TRUE)
df <- data.frame(id = rep(c(1, 2, 3, 4, 5, 6), each = 5),
Condition = rep(c(0, 1), each = 15),
time = c(1, 2, 3, 4, 5),
eat = eat
)
df$time <- as.factor(df$time)
df$Condition <- as.factor(df$Condition)
#Create the plot.
library(ggplot2)
ggplot(df, aes(x = time, y = eat, fill = Condition)) + geom_line() +
geom_point(size = 4, shape = 21) +
stat_summary(fun.y = mean, colour = "red", geom = "line")
The problem is, I need my lines to go horizontally (ie to show two different colored lines moving across the x-axis). But this code just connects the dots vertically:
If I don't convert Time to a factor, but only convert Condition to a factor, I get a mess of lines. The same thing happens in my actual data, as well.
I'd like it to look like this aesthetically, with the transparent error envelopes wrapping each line. However, I don't want it to be curvy, I want the lines to be straight, connecting the means at each point.
Here's the lines running in straight segments through the means of each time, with the range set to be the standard deviation of the points at the time. One stat.summary makes the mean line with the colour aesthetic, the other makes the area using the inherited fill aesthetic. ggplot2::mean_se is a convenient function that takes a vector and returns a data frame with the mean and +/- some number of standard errors. This is the right format for thefun.data argument to stat_summary, which passes these values to the geom specified. Here, geom_ribbon accepts ymin and ymax values to plot a ribbon across the graph.
library(tidyverse)
set.seed(12345)
eat <- sample(1:7, size = 30, replace = T)
df <- data.frame(
Condition = rep(c(0, 1), each = 15),
time = c(1, 2, 3, 4, 5),
eat = eat
)
df$Condition <- as.factor(df$Condition)
ggplot(df, aes(x = time, y = eat, fill = Condition)) +
geom_point(size = 4, shape = 21, colour = "black") +
stat_summary(geom = "ribbon", fun.data = mean_se, alpha = 0.2) +
stat_summary(
mapping = aes(colour = Condition),
geom = "line",
fun.y = mean,
show.legend = FALSE
)
Created on 2018-07-09 by the reprex package (v0.2.0).
Here's my best guess at what you want:
# keep time as numeric
df$time = as.numeric(as.character(df$time))
ggplot(df, aes(x = time, y = eat, group = Condition)) +
geom_smooth(
aes(fill = Condition, linetype = Condition),
method = "lm",
level = 0.65,
color = "black",
size = 0.3
) +
geom_point(aes(color = Condition))
Setting the level = 0.65 is about +/- 1 standard deviation on the linear model fit.
I think this code will get you most of the way there
library(tidyverse)
eat <- sample(1:7, size = 30, replace = TRUE)
tibble(id = rep(c(1, 2, 3, 4, 5, 6), each = 5),
Condition = factor(rep(c(0, 1), each = 15)),
time = factor(rep(c(1, 2, 3, 4, 5), 6)),
eat = eat) %>%
ggplot(aes(x = time, y = eat, fill = Condition, group = Condition)) +
geom_point(size = 4, shape = 21) +
geom_smooth()
geom_smooth is what you were looking for, I think. This creates a linear model out of the points, and as long as your x value is a factor, it should use the mean and connect the points that way.
install.packages("ggplot2")
library(ggplot2)
vector1 <- c(1, 4, 5, 6, 2, 4, 5, 8)
vector2 <- c(1, 2, 3, 4, 5, 6, 7, 8)
dataframe <- data.frame(vector1, vector2)
dataframe$vector2 <- as.factor(dataframe$vector2)
plot <- ggplot(dataframe, aes(vector2, vector1))
plot +geom_bar(stat = "identity")
I would like to make a text box somewhere in the bar chart window that shows values of 1-8 corresponding to levels of a factor. If I give the levels character-based names, it clutters the x-axis, and I don't want that. So I figured a legend that corresponds numbers to the levels would be great alternative. e.g. Ideally, each level of a factor is descending as a row, like a legend.
1 - slippery roads
2 - dry roads
3 - something creative
etc.
Ok here is another approach. There might be easier ones.
We use the guide for fill, remove the legend keys and overlay a second set of bars.
ggplot() + geom_col(data = dataframe, aes(vector2, vector1, fill = vector2)) +
geom_col(data = dataframe, mapping = aes(vector2, vector1)) +
scale_fill_discrete(name = "", labels = paste0(1:8, " roads")) +
theme(legend.position = c(.3, .8),
legend.key = element_blank(),
legend.background = element_blank()) +
guides(fill=guide_legend(override.aes=list(fill = NA),
keywidth = 0, keyheight = 0, nrow = 2))