Related
I'm drawing a scatterplot where I'd like to highlight different observations as time passes. Sometimes, these observations are close together, so I'm using geom_label_repel to do so. I'd also like to use enter_fade and exit_fade in order to make smoother the transition between phases of the animation.
I see from elsewhere (eg here) that the position of the geom_label_repel can be made consistent with the use of a seed. However, this isn't working for me with enter_fade and exit_fade: the geom_label_repel jumps around as the labels enter and exit.
Is there a way that the geom_label_repel can stay where it is through these phases?
Here's an example of how I've attempted to implement this, which hopefully will illustrate the problem I'm running into.
set.seed(24601)
library(stringi)
library(tidyverse)
library(gganimate)
library(ggrepel)
x <-
rnorm(100, 0, 1)
y <-
rnorm(100, 0, 1)
names <-
stri_rand_strings(100,
5)
categories <-
rep(c("a", "b", "c", "d", "e"), 5)
ggplot(data.frame(x, y, names, categories)) +
aes(x = x,
y = y) +
geom_point(data = . %>%
select(- categories)) +
geom_label_repel(aes(label = names,
group = categories),
seed = 24601) +
transition_states(categories) +
enter_fade() +
exit_fade()
What's happening is that during the transitions, the location and number of labels within the plot are not consistent. This causes geom_label_repel() to force labels away from each other. You can set force = 0 so that your labels are not repelled from each other (default force is 1), but instead only repelled from points.
ggplot(data.frame(x, y, names, categories)) +
aes(x = x,
y = y) +
geom_point(data = . %>%
select(- categories)) +
geom_label_repel(aes(label = names,
group = categories),
seed = 24601,
force = 0) +
transition_states(categories) +
enter_fade() +
exit_fade()
As you can see, you will have some labels overlap. However, if important, you could play with lower values of force (e.g. force = 0.1) so the labels only shift slightly but overlap less.
Although most are stable, I am getting a couple of random labels popping up and not transitioning, will investigate.
Why are the pies flat?
df<- data.frame(
Day=(1:6),
Var1=c(172,186,191,201,205,208),
Var2= c(109,483,64010,161992,801775,2505264), A=c(10,2,3,4.5,16.5,39.6), B=c(10,3,0,1.4,4.8,11.9), C=c(2,5,2,0.1,0.5,1.2), D=c(0,0,0,0,0.1,0.2))
ggplot() +
geom_scatterpie(data = df, aes(x = Var1 , y = Var2, group = Var1), cols = c("A", "B", "C", "D"))
I have tried using coord_fixed() and does not work either.
The problem seems to be the scales of the x- and y-axes. If you rescaled them to both to have zero mean and unit variance, the plot works. So, one thing you could do is plot the rescaled values, but transform the labels back into the original scale. To do this, you would have to do the following:
Make the data:
df<- data.frame(
Day=(1:6),
Var1=c(172,186,191,201,205,208),
Var2= c(109,483,64010,161992,801775,2505264), A=c(10,2,3,4.5,16.5,39.6), B=c(10,3,0,1.4,4.8,11.9), C=c(2,5,2,0.1,0.5,1.2), D=c(0,0,0,0,0.1,0.2))
Rescale the variables
df <- df %>%
mutate(x = c(scale(Var1)),
y = c(scale(Var2)))
Find the linear map that transforms the rescaled values back into their original values. Then, you can use the coefficients from the model to make a function that will transform the rescaled values back into the original ones.
m1 <- lm(Var1 ~ x, data=df)
m2 <- lm(Var2 ~ y, data=df)
trans_x <- function(x)round(coef(m1)[1] + coef(m1)[2]*x)
trans_y <- function(x)round(coef(m2)[1] + coef(m2)[2]*x)
Make the plot, using the transformation functions as the call to labels in the scale_[xy]_continuous() functions
ggplot() +
geom_scatterpie(data=df, aes(x = x, y=y), cols = c("A", "B", "C", "D")) +
scale_x_continuous(labels = trans_x) +
scale_y_continuous(labels = trans_y) +
coord_fixed()
There may be an easier way than this, but it wasn't apparent to me.
The range on the y-axis is so large it's compressing the disks to lines. Change the y-axis to a log scale, and you can see the shapes. Adding coord_fixed() to keep the pies circular:
ggplot() +
geom_scatterpie(data = df, aes(x = Var1 , y = Var2, group = Var1), cols = c("A", "B", "C", "D")) +
scale_y_log10() +
coord_fixed()
I have a data-frame 'x'
I want barplot like this
I tried
barplot(x$Value, names.arg = x$'Categorical variable')
ggplot(as.data.frame(x$Value), aes(x$'Categorical variable')
Nothing seems to work properly. In barplot, all axis labels (freq values) are different. ggplot is filling all bars to 100%.
You can try plotting using geom_bar(). Following code generates what you are looking for.
df = data.frame(X = c("A","B C","D"),Y = c(23,12,43))
ggplot(df,aes(x=X,y=Y)) + geom_bar(stat='identity') + coord_flip()
It helps to read the ggplot documentation. ggplot requires a few things, including data and aes(). You've got both of those statements there but you're not using them correctly.
library(ggplot2)
set.seed(256)
dat <-
data.frame(variable = c("a", "b", "c"),
value = rnorm(3, 10))
dat %>%
ggplot(aes(x = variable, y = value)) +
geom_bar(stat = "identity", fill = "blue") +
coord_flip()
Here, I'm piping my dat to ggplot as the data argument and using the names of the x and y variables rather than passing a data$... value. Next, I add the geom_bar() statement and I have to use stat = "identity" to tell ggplot to use the actual values in my value rather than trying to plot the count of the number.
You have to use stat = "identity" in geom_bar().
dat <- data.frame("cat" = c("A", "BC", "D"),
"val" = c(23, 12, 43))
ggplot(dat, aes(as.factor(cat), val)) +
geom_bar(stat = "identity") +
coord_flip()
Following is a short code to generate a barplot with an added layer of line plot. I have added comments indicating what works and what doesn't. While my problem is solved, I can't understand why I had a problem or how it got solved. If you can explain or suggest the right way to do it, that would be nice.
library(ggplot2)
factors <- c("A", "B", "C", "D", "B", "A", "C", "B", "D", "D")
data <- data.frame(n=1:10, a= runif(10, 1, 5), b=runif(10, 1, 5),c=runif(10, 1, 5))
gg_data <- melt(data, id.vars="n", variable.name="var")
gg_data$alp <- rep(factors, 3)
gg_data1 <- melt(data.frame(n=1:10, a= runif(10, 2, 3), b=runif(10, 4, 5),c=runif(10, 3, 4)), id.vars="n", variable.name="var")
#this does not work
ggplot(data= gg_data, aes(x=n, y=value, fill=alp))+geom_bar(stat="identity")+ facet_grid( var ~ ., scale="free_y")+geom_line(data= gg_data1, aes(x= n, y=value))
#this gives a weird output
gg_data1$alp <- rep(factors, 3)
ggplot(data= gg_data, aes(x=n, y=value, fill=alp))+geom_bar(stat="identity")+ facet_grid( var ~ ., scale="free_y")+geom_line(data= gg_data1, aes(x= n, y=value))
#this works the way I want it to, don't know why.
gg_data1$alp <- "A"
ggplot(data= gg_data, aes(x=n, y=value, fill=alp))+geom_bar(stat="identity")+ facet_grid( var ~ ., scale="free_y")+geom_line(data= gg_data1, aes(x= n, y=value))
Basically your plots are combining information from the two datasets to try to get a new plot. Since you have listed that fill = alp, then ggplot is trying to apply this information to all of your plots.
The easiest way to see this is consider this new data.frame:
gg1 <- gg_data1
names(gg1) <- c("n1", "var1", "value1")
gg_combine <- cbind(gg_data, gg1)
To reproduce your 2nd graph it is equivalent to:
ggplot(data=gg_combine, aes(x=n, y=value, fill=alp))+
geom_bar(stat="identity")+
geom_line(aes(x=n1, y=value1, colour=alp)) +
facet_grid( var ~ ., scale="free_y")
Basically what it is saying is I want to group everything by "alp" and plot them together by those groups, which is why you get those lines; with the addition of colour=alp then it becomes clear why the lines look that way.
With your last plot. What you've done is only group the bar plots with alp, but with the lines we want to ignore this grouping. This is equivalent to:
ggplot(data=gg_combine, aes(x=n, y=value))+
geom_bar(aes(fill=alp), stat="identity")+
geom_line(aes(x=n1, y=value1)) +
facet_grid( var ~ ., scale="free_y")
Hope this helps.
I have created the following graphic ggplot
with the following code;
p <- ggplot(df, aes(x=100*prop_select, y=(1500-s_meanResponse), fill=product)) +
geom_bar(stat='identity', width=2, alpha=.6, color='#333333') +
coord_cartesian(xlim = c(0, 5)) +
coord_flip()
print(p)
I am attempting to intentionally overlap the bars. I would like to know how to change the z-index (depth) of each of the bars. I attempted to do this by simply reordering the levels of the factor column that determines my bars
# Order by mean response to make sure that bars are layered correctly (does not work!)
# Switching this minus makes no difference to the bar z-index but does reverse legend entries
df <- df[sort.list(-df$s_meanResponse),]
df$product <- factor(df$product, levels=df$product)
Anybody know if this is possible with ggplot2?
EDIT:
dataframe is structured similar to below
df <- data.frame( product=c('a','b','c'), s_meanResponse=c(1120,1421,1320), prop_select=c(.3,.2,.5))
I'm using the following df with actual overlapping:
df <- data.frame(product=c('a','b','c'),
s_meanResponse=c(1120,1421,1320),
prop_select=c(.311,.32,.329))
It seems that the plotting order remains the same regardless of the factor levels ordering, instead it just plots bars from lowest to highest y-value. To achieve custom ordering, we'll have to do the following, plotting layers explicitly one by one in the desired order:
geom_bars_with_order <- function(vals)
{
l <- list()
for (i in vals)
{
l <- c(l, geom_bar(data = df[df$product == i, ],
stat='identity', width=2, alpha=.6, color='#333333'))
}
l
}
# default order
ggplot(NULL, aes(x=100*prop_select, y=(1500-s_meanResponse), fill=product)) +
geom_bars_with_order(c("a", "b", "c")) +
coord_cartesian(xlim = c(0, 5)) +
coord_flip()
# custom order, "a" on top
ggplot(NULL, aes(x=100*prop_select, y=(1500-s_meanResponse), fill=product)) +
geom_bars_with_order(c("b", "c", "a")) +
coord_cartesian(xlim = c(0, 5)) +
coord_flip()