Hi supposed I have the following pie info.
df=structure(list(Var1 = c("a", "b"), Freq = c(306L, 1064L), per = c(0.223357664233577,
0.776642335766423)), row.names = c(NA, -2L), class = "data.frame")
and I plot this pie chart with direction -1
ggplot(data = df,
aes(x = "", y = per, fill = Var1)) +
geom_col() +
geom_text(aes(label = scales::percent(per, accuracy = 1)),
position = position_stack(vjust = 0.5),
color = "grey20", size = pietext ) +
coord_polar(theta = "y", direction =-1 ) +
theme_void ()
However what I would like is to label with with the frequency rather than the percentage.
Var1 Freq per
1 a 306 0.2233577
2 b 1064 0.7766423
Is this possible with this method? I tried replacing per with Freq but that just gave some really strange text.
thank you.
aes(label = Freq) is the way to go:
ggplot(data = df,
aes(x = "", y = per, fill = Var1)) +
geom_col() +
geom_text(aes(label = Freq),
position = position_stack(vjust = 0.5),
color = "grey20", size=12) +
coord_polar(theta = "y", direction =-1) +
theme_void ()
Just change geom_text(aes(label =Freq)
ggplot(data = df, aes(x = "", y = per, fill = Var1)) +
geom_col() +
geom_text(aes(label =Freq),
position = position_stack(vjust = 0.5),
color = "black", size = 10 ) +
labs( x="", y="", fill="")+
scale_fill_manual(values=c("#4E79A7", "#fc7d0b"))+
coord_polar(theta = "y", direction =-1 ) +
theme_no_axes()
Plot:
or something that is better than a pie chart
Sample code:
library(waffle)
library(ggthemes)
vals <- c(306,1064)
val_names <- sprintf("%s (%s)", c("a","b"), label=vals)
names(vals) <- val_names
waffle::waffle(vals) +
ggthemes::scale_fill_tableau(name=NULL)
Plot:
Sample code:
df=structure(list(Var1 = c("a", "b"), Freq = c(306L, 1064L), per = c(0.223357664233577, 0.776642335766423)), row.names = c(NA, -2L), class = "data.frame")
Related
This question builds off of enter link description here but is in the context of faceted boxplots.
So, I have the following code:
set.seed(20210714)
dd <- data.frame(Method = rep(c("A", "B", "C"), each = 60), Pattern = rep(c("X", "Y", "Z"), times = 30), X1 = runif(180), Complexity = rep(c("High", "Low"), times = 90), nsim = rep(rep(1:10, times = 9), each = 2), n = 10)
dd1 <- data.frame(Method = rep(c("A", "B", "C"), each = 60), Pattern = rep(c("X", "Y", "Z"), times = 30), X1 = runif(180), Complexity = rep(c("High", "Low"), times = 90), nsim = rep(rep(1:10, times = 9), each = 2), n = 5)
dd <- rbind(dd, dd1)
library(ggplot2)
# create dummy dataframe.
dummy.df <- dd
dummy.df[nrow(dd) + 1:2,"Pattern"] <- unique(dd$Pattern)[-3]
dummy.df[nrow(dd) + 1:2,"Method"] <- "ZZZ"
dummy.df[nrow(dd) + 1:2,"Complexity"] <- c("High","Low")
dummy.df$dummy <- interaction(dummy.df$Method,dummy.df$Pattern)
ggplot(dummy.df, aes(x = dummy, y = X1, fill = Method)) +
geom_boxplot(aes(fill = Method)) +
facet_grid(~Complexity) +
theme_light() +
theme(legend.position = 'bottom') +
guides(fill = guide_legend(nrow=1)) +
geom_line(aes(x = dummy,
group=interaction(Pattern,nsim)),
size = 0.35, alpha = 0.35, colour = I("#525252")) +
geom_point(aes(x = dummy,
group=interaction(Pattern,nsim)),
size = 0.35, alpha = 0.25, colour = I("#525252")) +
scale_x_discrete(labels = c("","X", "", "", "", "Y", "", "", "", "Z","","")) +
xlab("Pattern") +
scale_fill_brewer(breaks=c("A", "B", "C"), type="qual", palette="Paired")
dummy.df <- dd
dummy.df[nrow(dd) + 1:2,"Pattern"] <- unique(dd$Pattern)[-3]
dummy.df[nrow(dd) + 1:2,"Method"] <- "ZZZ"
dummy.df[nrow(dd) + 1:2,"Complexity"] <- c("High","Low")
dummy.df$dummy <- interaction(dummy.df$Method,dummy.df$Pattern)
dummy.df$fill <- interaction(dummy.df$Method, dummy.df$n)
dummy.df$dummy <- interaction(dummy.df$fill, dummy.df$Pattern)
dummy.df$dummy <- factor(dummy.df$dummy, levels = levels(dummy.df$dummy)[-c(4, 12, 20, 24)])
dummy.df$dummy[361:362] <- "A.10.Z" ## dummy variables to get rid of NAs
theme_set(theme_bw(base_size = 14))
ggplot(dummy.df, aes(x = dummy, y = X1, fill = fill)) +
geom_boxplot(aes(fill = fill),lwd=0.1,outlier.size = 0.01) +
facet_grid(~Complexity) +
theme(legend.position = 'bottom') +
guides(fill = guide_legend(nrow=1)) +
geom_line(aes(x = dummy,
group=interaction(Pattern,nsim,n)),
size = 0.35, alpha = 0.35, colour = I("#525252")) +
geom_point(aes(x = dummy,
group=interaction(Pattern,nsim,n)),
size = 0.35, alpha = 0.25, colour = I("#525252")) +
scale_x_discrete(labels = c("X", "Y", "Z"), breaks = paste("A.10.", c("X", "Y", "Z"), sep = ""),drop=FALSE) +
xlab("Pattern") +
scale_fill_brewer(breaks= levels(dummy.df$fill)[-c(4,8)], type="qual", palette="Paired")
This yields the following plot.
All is well, except with the legend. I would like the following: the dark colors to be in the First group titled "n=5" on the left, with "A", "B", "C" for the three dark colors, and the light colors to be to the right, in a Second group titled "n=10" on the right, with "A", "B", "C" for the three light colors. Sort of like in the link enter link description here above.
What I can not figure out is how to call the boxplot twice to mimic the solution there.
Is there a way to do this? Please feel free to let me know if the question is not clear.
Thanks again, in advance, for any help!
Adapting my answer on your former question this could be achieved like so:
library(ggplot2)
fill <- levels(dummy.df$fill)[-c(4,8)]
fill <- sort(fill)
labels <- gsub("\\.\\d+", "", fill)
labels <- setNames(labels, fill)
colors <- scales::brewer_pal(type="qual", palette="Paired")(6)
colors <- setNames(colors, fill)
library(ggnewscale)
ggplot(dummy.df, aes(x = dummy, y = X1, fill = fill)) +
geom_boxplot(aes(fill = fill), lwd=0.1,outlier.size = 0.01) +
scale_fill_manual(name = "n = 5", breaks= fill[grepl("5$", fill)], labels = labels[grepl("5$", fill)], values = colors,
guide = guide_legend(title.position = "left", order = 1)) +
new_scale_fill() +
geom_boxplot(aes(fill = fill), lwd=0.1,outlier.size = 0.01) +
scale_fill_manual(name = "n = 10", breaks = fill[grepl("10$", fill)], labels = labels[grepl("10$", fill)], values = colors,
guide = guide_legend(title.position = "left", order = 2)) +
facet_grid(~Complexity) +
theme(legend.position = 'bottom') +
guides(fill = guide_legend(nrow=1)) +
geom_line(aes(x = dummy,
group=interaction(Pattern,nsim,n)),
size = 0.35, alpha = 0.35, colour = I("#525252")) +
geom_point(aes(x = dummy,
group=interaction(Pattern,nsim,n)),
size = 0.35, alpha = 0.25, colour = I("#525252")) +
scale_x_discrete(labels = c("X", "Y", "Z"), breaks = paste("A.10.", c("X", "Y", "Z"), sep = ""),drop=FALSE) +
xlab("Pattern")
#> Warning: Removed 2 rows containing non-finite values (new_stat_boxplot).
This is what is the output.I have a data set which contains unit, weight of each unit and compliance score for each unit in year 2016.
I was not able to add the table but here is the screenshot for the data in csv
I have named the columns in the data as unit, weight and year(which is compliance score) .
I want to create a sunburst chart where the first ring will be the unit divided based on weight and the second ring will be the same but will have labels compliance score.
The colour for each ring will be different.
I was able to do some code with the help from an online blog and the output I have gotten is similar to what I want but I am facing difficulty in positioning of the labels and also the colour coding for each ring
#using ggplot
library(ggplot2) # Visualisation
library(dplyr) # data wrangling
library(scales) # formatting
#read file
weight.eg = read.csv("Dummy Data.csv", header = FALSE, sep =
";",encoding = "UTF-8")
#change column names
colnames(weight.eg) <- c ("unit","weight","year")
#as weight column is factor change into integer
weight.eg$weight = as.numeric(levels(weight.eg$weight))
[as.integer(weight.eg$weight)]
weight.eg$year = as.numeric(levels(weight.eg$year))
[as.integer(weight.eg$year)]
#Nas are introduced, remove
weight.eg <- na.omit(weight.eg)
#Sum of the total weight
sum_total_weight = sum(weight.eg$weight)
#First layer
firstLevel = weight.eg %>% summarize(total_weight=sum(weight))
sunburst_0 = ggplot(firstLevel) # Just a foundation
#this will generate a bar chart
sunburst_1 =
sunburst_0 +
geom_bar(data=firstLevel, aes(x=1, y=total_weight),
fill='darkgrey', stat='identity') +
geom_text(aes(x=1, y=sum_total_weight/2, label=paste("Total
Weight", comma(total_weight))), color='black')
#View
sunburst_1
#this argument is used to rotate the plot around the y-axis which
the total weight
sunburst_1 + coord_polar(theta = "y")
sunburst_2=
sunburst_1 +
geom_bar(data=weight.eg,
aes(x=2, y=weight.eg$weight, fill=weight.eg$weight),
color='white', position='stack', stat='identity', size=0.6)
+
geom_text(data=weight.eg, aes(label=paste(weight.eg$unit,
weight.eg$weight), x=2, y=weight.eg$weight), position='stack')
sunburst_2 + coord_polar(theta = "y")
sunburst_3 =
sunburst_2 +
geom_bar(data=weight.eg,
aes(x=3, y=weight.eg$weight,fill=weight.eg$weight),
color='white', position='stack', stat='identity',
size=0.6)+
geom_text(data = weight.eg,
aes(label=paste(weight.eg$year),x=3,y=weight.eg$weight),position =
'stack')
sunburst_3 + coord_polar(theta = "y")
sunburst_3 + scale_y_continuous(labels=comma) +
scale_fill_continuous(low='white', high='darkred') +
coord_polar('y') + theme_minimal()
Output for dput(weight.eg)
structure(list(unit = structure(2:7, .Label = c("", "A", "B",
"C", "D", "E", "F", "Unit"), class = "factor"), weight = c(30,
25, 10, 17, 5, 13), year = c(70, 80, 50, 30, 60, 40)), .Names =
c("unit",
"weight", "year"), row.names = 2:7, class = "data.frame", na.action
= structure(c(1L,
8L), .Names = c("1", "8"), class = "omit"))
output for dput(firstLevel)
structure(list(total_weight = 100), .Names = "total_weight", row.names
= c(NA,
-1L), na.action = structure(c(1L, 8L), .Names = c("1", "8"), class =
"omit"), class = "data.frame")
So I think I might have some sort of solution for you. I wasn't sure what you wanted to color-code on the outer ring; from your code it seems you wanted it to be the weight again, but it was not obvious to me. For different colour scales per ring, you could use the ggnewscale package:
library(ggnewscale)
For the centering of the labels you could write a function:
cs_fun <- function(x){(cumsum(x) + c(0, cumsum(head(x , -1))))/ 2}
Now the plotting code could look something like this:
ggplot(weight.eg) +
# Note: geom_col is equivalent to geom_bar(stat = "identity")
geom_col(data = firstLevel,
aes(x = 1, y = total_weight)) +
geom_text(data = firstLevel,
aes(x = 1, y = total_weight / 2,
label = paste("Total Weight:", total_weight)),
colour = "black") +
geom_col(aes(x = 2,
y = weight, fill = weight),
colour = "white", size = 0.6) +
scale_fill_gradient(name = "Weight",
low = "white", high = "darkred") +
# Open up new fill scale for next ring
new_scale_fill() +
geom_text(aes(x = 2, y = cs_fun(weight),
label = paste(unit, weight))) +
geom_col(aes(x = 3, y = weight, fill = weight),
size = 0.6, colour = "white") +
scale_fill_gradient(name = "Another Weight?",
low = "forestgreen", high = "white") +
geom_text(aes(label = paste0(year), x = 3,
y = cs_fun(weight))) +
coord_polar(theta = "y")
Which looks like this:
giving the following data:
data2 <- list(structure(list(super_group = c(1,1), Group.1 = structure(3:4, .Label = c("A","B", "C", "D", "E", "F"), class = "factor"), Pr1 = c(65, 75), Pr2 = c(54, 88), Prh = c(25, 5), SE = c(25, 75 )), row.names = c(NA, -2L), class = "data.frame"), NULL, structure(list(super_group = c(3,3), Group.1 = structure(3:4, .Label = c("A","B", "C", "D", "E", "F"), class = "factor"), Pr1 = c(81,4), Pr2 = c(66, 57),Prh = c(3,3), SE = c(8, 9)), row.names = c(NA,
-2L), class = "data.frame"))
to plot using ggplot2:
data2 %>%
bind_rows() %>%
ggplot(., aes(x = Group.1, y = Pr1, fill = Group.1)) +
geom_bar(stat = "identity") +
facet_grid(. ~ super_group)
-you see C and D labels in the x axis which are not necessary. So I want to remove them and reduce the width of the bars. any ideas?
-can we move 1 and 3 from x axis top to x axis bottom?
We could use switch argument to facet_grid to change the position of facet labels.
Arguments axis.text.x and axis.ticks.x control the text and tick on the x axis. To remove them declare them as element_blank().
library(tidyverse)
data2 %>%
bind_rows() %>%
ggplot(., aes(x = Group.1, y = Pr1, fill = Group.1)) +
geom_bar(stat = "identity") +
facet_grid(. ~ super_group, switch = "x") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) -> p1
To change the proportions of the graph save it with different dimensions. Example:
ggsave("p1.pdf", plot = p1, device = "pdf", width = 3, height = 5)
Or if using knitr change the chunk options by defining:
fig.width=3, fig.height=5 for example:
```{r p1, fig.width=3, fig.height=5}
data2 %>%
bind_rows() %>%
ggplot(., aes(x = Group.1, y = Pr1, fill = Group.1)) +
geom_bar(stat = "identity") +
facet_grid(. ~ super_group, switch = "x") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank())
```
and to change the width of the bars use argument width:
data2 %>%
bind_rows() %>%
ggplot(., aes(x = Group.1, y = Pr1, fill = Group.1)) +
geom_bar(stat = "identity", width = 0.5) +
facet_grid(. ~ super_group, switch = "x") +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank())
another option (based on the comments it seems to me this is the desired one) is to change expand:
data2 %>%
bind_rows() %>%
ggplot(., aes(x = Group.1, y = Pr1, fill = Group.1)) +
geom_bar(stat = "identity") +
facet_grid(. ~ super_group, switch = "x") +
scale_x_discrete(expand = c(1,1))+
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank())
I have created a list with a count of the values of 1 column:
ataques_tot <- count(t1$attacktype1_txt)
ataques_tot
x freq
1 Armed Assault 40223
2 Assassination 18402
3 Bombing/Explosion 83073
4 Facility/Infrastructure Attack 9581
5 Hijacking 11733
6 Unarmed Assault 913
7 Unknown 6425
And I want to make a piechart with the percentages, not with the counts out of it. I have tried to take that list to a df and then using something like this:
ggpie(ataques_tot, "value", label = "group",
fill = "group", color = "white")
But I am struggling a lot, maybe that option is already implemented on ggplot2...
I have tried also this:
pie <- ggplot(t1, aes(x = factor(1), fill = factor(attacktype1_txt))) +
geom_bar(width = 1)
pie + coord_polar(theta = "y")
But it gives me a count, not the percentages of the categorical variable. After that I would just need to entitle the plot and that's it.
Calculate the percentage:
d$perc <- round(100 * d$freq / sum(d$freq))
Then plot:
ggplot(data = d, aes(x = 0, y = freq, fill = x)) +
geom_bar(stat = "identity") +
geom_text(aes(label = perc), position = position_stack(vjust = 0.5)) +
scale_x_continuous(expand = c(0,0)) +
labs(fill = 'Type', x = NULL, y = NULL, title = 'Deaths', subtitle = 'in perventages') +
coord_polar(theta = "y") +
theme_minimal()
which gives:
Used data:
d <- structure(list(x = c("Armed Assault", "Assassination", "Bombing/Explosion", "Facility/Infrastructure Attack", "Hijacking", "Unarmed Assault", "Unknown"),
freq = c(40223L, 18402L, 83073L, 9581L, 11733L, 913L, 6425L)),
.Names = c("x", "freq"), class = "data.frame", row.names = c(NA, -7L))
Here is a data frame:
library(tidyverse)
example_df <- structure(list(Funnel = c("Sessions", "AddToCart", "Registrations", "ShippingDetails", "Checkout", "Transactions"), Sum = c(1437574, 385281, 148181, 56989, 35613, 29671), End = c(NA, 1437574, 385281, 148181, 56989, 35613), xpos = c(0.5, 1.5, 2.5, 3.5, 4.5, 5.5), Diff = c(NA, 1052293, 237100, 91192, 21376, 5942), Percent = c("NA %", "73.2 %", "61.5 %", "61.5 %", "37.5 %", "16.7 %")), .Names = c("Funnel", "Sum", "End", "xpos", "Diff", "Percent"), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -6L))
And here is a ggplot2:
ggplot(example_df, aes(x = reorder(Funnel, -Sum), y = Sum)) +
geom_col(alpha = 0.6, fill = "#008080") +
stat_summary(aes(label = scales::comma(..y..)), fun.y = 'sum',
geom = 'text', col = 'white', vjust = 1.5) +
geom_segment(aes(x=xpos, y = End, xend = xpos, yend = Sum)) +
geom_text(aes(x=xpos,y = End-Diff / 2, label=Percent), hjust = -0.2) +
theme(axis.title.x = element_blank(),
axis.title.y = element_blank()) +
scale_y_continuous(labels = function(l) {l = l / 1000; paste0(l, "K")}) +
Here's what it looks like:
The values on the plot from Shipping Details: Transactions are tricky to read because the bars are smaller.
I wondered if there was a good approach to dealing with this. I tried extending the range with:
+ expand_limits(y = -100000)
But that just lowers the y axis.
Is there a sensible solution to visualizing the data points in a way they are not squished? If I could somehow lower the green bars into the minus region without impacting the proportions?
Very dirty solution, but works. Add dummy geom_bar's bellow each segment (ie., extend original segment by adding negative bar) with the same color and alpha.
Bars to add:
geom_bar(data = data.frame(x = example_df$Funnel, y = -2e4),
aes(x, y),
stat = "identity", position = "dodge",
alpha = 0.6, fill = "#008080")
Final code:
# Using OPs data
library(ggplot2)
ggplot(example_df, aes(x = reorder(Funnel, -Sum), y = Sum)) +
geom_col(alpha = 0.6, fill = "#008080") +
geom_segment(aes(x=xpos, y = End, xend = xpos, yend = Sum)) +
geom_text(aes(x=xpos,y = End-Diff / 2, label=Percent), hjust = -0.2) +
theme(axis.title.x = element_blank(),
axis.title.y = element_blank()) +
scale_y_continuous(labels = function(l) {l = l / 1000; paste0(l, "K")}) +
geom_bar(data = data.frame(x = example_df$Funnel, y = -2e4),
aes(x, y),
stat = "identity", position = "dodge",
alpha = 0.6, fill = "#008080") +
stat_summary(aes(label = scales::comma(..y..)), fun.y = 'sum',
geom = 'text', col = 'white', vjust = 1.5) +
theme_classic()
Plot:
PS:
You have to add stat_summary after geom_bar