I'd like to use position dodge to offset one variable in my ggplot chart (in this case banana) and leave the other two variables (red_apple and green_apple) without an offset. Using position_dodge applies the offset to each variable, but I'd like to choose which variables are offset specifically.
library(ggplot2)
data <- data.frame(Place = c(rep('Place_A',30),rep('Place_B',30)),
variable = c(rep(c(rep('red_Apple',10),rep('green_Apple',10),rep('bananna',10)),2)),
value = rep(c(1:10,1:10-.05,1:10+.2),2))
dodge = position_dodge(.5)
ggplot(data, aes(Place, value)) +
geom_point(aes(color=variable),position=dodge)
Is there for example a way to scale position manually, like how you can do for other aesthetics?
This obviously throws an error, but is what I was hoping for...
ggplot(data, aes(Place, value)) +
geom_point(aes(color=variable, position = variable)) +
scale_position_manual(breaks = c('green_Apple','red_Apple','bananna'),
values = c(position_dodge(0),position_dodge(0),position_dodge(.5)))
Does this look like what you want?
data$grp = ifelse(data$variable == "bananna", 2, 1)
ggplot(data, aes(Place, value, group = grp)) +
geom_point(aes(color=variable), position = position_dodge(0.5))
Related
I want to create a side by side barplot using geom_bar() of this data frame,
> dfp1
value percent1 percent
1 (18,29] 0.20909091 0.4545455
2 (29,40] 0.23478261 0.5431034
3 (40,51] 0.15492958 0.3661972
4 (51,62] 0.10119048 0.1726190
5 (62,95] 0.05660377 0.1194969
With values on the x-axis and the percents as the side by side barplots. I have tried using this code,
p = ggplot(dfp1, aes(x = value, y= c(percent, percent1)), xlab="Age Group")
p = p + geom_bar(stat="identity", width=.5)
However, I get this error: Error: Aesthetics must either be length one, or the same length as the dataProblems:value. My percent and percent1 are the same length as value, so I am confused. Thanks for the help.
You will need to melt your data first over value. It will create another variable called value by default, so you will need to renames it (I called it percent). Then, plot the new data set using fill in order to separate the data into groups, and position = "dodge" in order put the bars side by side (instead of on top of each other)
library(reshape2)
library(ggplot2)
dfp1 <- melt(dfp1)
names(dfp1)[3] <- "percent"
ggplot(dfp1, aes(x = value, y= percent, fill = variable), xlab="Age Group") +
geom_bar(stat="identity", width=.5, position = "dodge")
Similar to David's answer, here is a tidyverse option using tidyr::pivot_longer to reshape the data before plotting:
library(tidyverse)
dfp1 %>%
pivot_longer(-value, names_to = "variable", values_to = "percent") %>%
ggplot(aes(x = value, y = percent, fill = variable), xlab="Age Group") +
geom_bar(stat = "identity", position = "dodge", width = 0.5)
I am trying to create a swimlane plot of different subjects doses over time. When I run my code the bars are stacked by amount of dose. My issue is that subjects doses vary they could have 5, 10 , 5 in my plot the 5's are stacked together. But I want the represented as they happen over time. In my data set I have the amount of time each patient was on a dose for ordered by when they had the dose. I want by bars stacked by ordering variable called "p" which is numeric is goes 1,2,3,4,5,6 etc which what visit the subject had that dose.
ggplot(dataset,aes(x=diff+1, y=subject)) +
geom_bar(stat="identity", aes(fill=as.factor(EXDOSE))) +
scale_fill_manual(values = dosecol, name="Actual Dose in mg")
I want the bars stacked by my variable "p" not by fill
I tried forcats but that does not work. Unsure how to go about this the data in the dataset is arranged by p for each subject
example data
dataset <- data.frame(subject = c("1002", "1002", "1002", "1002", "1034","1034","1034","1034"),
exdose = c(5,10,20,5,5,10,20,20),
p= c(1,2,3,4,1,2,3,4),
diff = c(3,3,9,7,3,3,4,5)
)
ggplot(dataset,aes(x=diff+1, y=subject)) +
geom_bar(stat="identity", aes(fill=as.factor(exdose)),position ="stack") +
scale_fill_manual(values = dosecol, name="Actual Dose in mg")
If you want to order your stacked bar chart by p you have to tell ggplot2 to do so by mapping p on the group aesthetic. Otherwise ggplot2 will make a guess which by default is based on the categorical variables mapped on any aesthetic, i.e. in your case the fill aes:
Note: I dropped the scale_fill_manual as you did not provide the vector of colors. But that's not important for the issue.
library(ggplot2)
ggplot(dataset, aes(x = diff + 1, y = subject, group = p)) +
geom_col(aes(fill = as.factor(exdose)))
EDIT And to get the right order we have to reverse the order of the stack which could be achieved using position_stack(reverse = TRUE):
Note: To check that we have the right order I added a geom_text showing the p value.
ggplot(dataset, aes(x = diff + 1, y = subject, group = p)) +
geom_col(aes(fill = as.factor(exdose)), position = position_stack(reverse = TRUE)) +
geom_text(aes(label = p), position = position_stack(reverse = TRUE))
Second option would be to convert p to a factor which the order of levels set in the reverse order:
ggplot(dataset, aes(x = diff + 1, y = subject, group = factor(p, rev(sort(unique(p)))))) +
geom_col(aes(fill = as.factor(exdose))) +
geom_text(aes(label = p), position = "stack")
I have this data set and I want to fill the area under each line. However I get an error saying:
Error: stat_bin() must not be used with a y aesthetic.
Additionally, I need to use alpha value for transparency. Any suggestions?
library(reshape2)
library(ggplot2)
dat <- data.frame(
a = rnorm(12, mean = 2, sd = 1),
b = rnorm(12, mean = 4, sd = 2),
month = c("JAN","FEB","MAR",'APR',"MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"))
dat$month <- factor(dat$month,
levels = c("JAN","FEB","MAR",'APR',"MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"),
ordered = TRUE)
dat <- melt(dat, id="month")
ggplot(data = dat, aes(x = month, y = value, colour = variable)) +
geom_line() +
geom_area(stat ="bin")
I want to fill the area under each line
This means we will need to specify the fill aesthetic.
I get an error saying "Error: stat_bin() must not be used with a y aesthetic."
This means we will need to delete your stat ="bin" code.
Additionally, I need to use alpha value for transparency.
This means we need to put alpha = <some value> in the geom_area layer.
Two other things: (1) since you have a factor on the x-axis, we need to specify a grouping so ggplot knows which points to connect. In this case we can use variable as the grouper. (2) The default "position" of geom_area is to stack the areas rather than overlap them. Because you ask about transparency I assume you want them overlapping, so we need to specify position = 'identity'.
ggplot(data = dat, aes(x = month, y = value, colour = variable)) +
geom_line() +
geom_area(aes(fill = variable, group = variable),
alpha = 0.5, position = 'identity')
To get lines across categorical variables, use the group aesthetic:
ggplot(data = dat, aes(x = month, y = value, colour = variable, group = variable)) +
#geom_line(position = 'stack') + # redundant, but this is where lines are drawn
geom_area(alpha = 0.5)
To change the color inside, use the fill aesthetic.
This question already has answers here:
Showing data values on stacked bar chart in ggplot2
(3 answers)
Closed 6 years ago.
I would like to position the corresponding value labels in a geom_col stacked barchart in the middle of each bar segment.
However, my naive attempt fails.
library(ggplot2) # Version: ggplot2 2.2
dta <- data.frame(group = c("A","A","A",
"B","B","B"),
sector = c("x","y","z",
"x","y","z"),
value = c(10,20,70,
30,20,50))
ggplot(data = dta) +
geom_col(aes(x = group, y = value, fill = sector)) +
geom_text(position="stack",
aes(x = group, y = value, label = value))
Obviously, setting y=value/2 for geom_text does not help, either. Besides, the text is positioned in the wrong order (reversed).
Any (elegant) ideas how to solve this?
You need to have a variable mapped to an aesthetic to represent the groups in geom_text. For you, this is your "sector" variable. You can use it with the group aesthetic in geom_text.
Then use position_stack with vjust to center the labels.
ggplot(data = dta) +
geom_col(aes(x = group, y = value, fill = sector)) +
geom_text(aes(x = group, y = value, label = value, group = sector),
position = position_stack(vjust = .5))
You could save some typing by setting your aesthetics globally. Then fill would be used as the grouping variable for geom_text and you can skip group.
ggplot(data = dta, aes(x = group, y = value, fill = sector)) +
geom_col() +
geom_text(aes(label = value),
position = position_stack(vjust = .5))
I'm hoping to use ggplot2 to generate a set of stacked bars in pairs, much like this:
With the following example data:
df <- expand.grid(name = c("oak","birch","cedar"),
sample = c("one","two"),
type = c("sapling","adult","dead"))
df$count <- sample(5:200, size = nrow(df), replace = T)
I would want the x-axis to represent the name of the tree, with two bars per tree species: one bar for sample one and one bar for sample two. Then the colors of each bar should be determined by type.
The following code generates the stacked bar with colors by type:
ggplot(df, aes(x = name, y = count, fill = type)) + geom_bar(stat = "identity")
And the following code generates the dodged bars by sample:
ggplot(df, aes(x = name, y = count, group = sample)) + geom_bar(stat = "identity", position = "dodge")
But I can't get it to dodge one of the groupings (sample) and stack the other grouping (type):
ggplot(df, aes(x = name, y = count, fill = type, group = sample)) + geom_bar(stat = "identity", position = "dodge")
One workaround would be to put interaction of sample and name on x axis and then adjust the labels for the x axis. Problem is that bars are not put close to each other.
ggplot(df, aes(x = as.numeric(interaction(sample,name)), y = count, fill = type)) +
geom_bar(stat = "identity",color="white") +
scale_x_continuous(breaks=c(1.5,3.5,5.5),labels=c("oak","birch","cedar"))
Another solution is to use facets for name and sample as x values.
ggplot(df,aes(x=sample,y=count,fill=type))+
geom_bar(stat = "identity",color="white")+
facet_wrap(~name,nrow=1)