How to adjust barchart in ggplotly? - r

I have barchart with dual-axis in order to visualize 3 numerical variables. All these work pretty nice in ggplot. However, when I convert ggplot to ggplotly, there are issues:
in the legend, there are strange 1s (highlighted in yellow)
in the hover, there are double values (highlighted in yellow)
changes of hjust=0, vjust=-0.5 in geom_text are not reflected on the plot
Could anybody help me to adjust these issues?
df <- data.frame (model = c("A", "B", "C","D","E","F"),
share = c(12,20,15,9,60,20),
sale = c(16,25,18,14,67,28),
cost = c(14,19,28,24,57,28))
#set levels of model by cost
df$model <- factor(df$model, levels = arrange(df, desc(df$cost))$model)
library(tidyverse)
df_long <- df %>%
pivot_longer(
cols = -model
)
plt <- ggplot(df_long, aes(x = model, y= value, label=value))+
geom_col(data = filter(df_long, name != "cost"), aes(fill=name), position = position_dodge())+
scale_fill_manual(values = c("blue", "grey"))+
geom_line(data = filter(df_long, name == "cost"), aes(color = name, group = 1), size = 1)+
scale_color_manual(values = "red")+
geom_text(data = filter(df_long, name == "cost"), size = 3,hjust=0, vjust=-0.5)+
geom_label(data = filter(df_long, name == "cost"), hjust=0, vjust=-0.5)+
scale_y_continuous(
name = "Sale and Share",
sec.axis = sec_axis(~., name ="Cost")
)+
theme_minimal()+
theme(legend.title=element_blank())
ggplotly(plt)

Further approach from #Quinten's answer,
to handle 'name name' and 'value value' things,
try
tooltip = c("value", "name", "model")
plt1$x$layout$legend$title$text <- "name"
Full code is
plt <-
ggplot(df_long, aes(x = model, y= value, label = NA))+
geom_col(data = filter(df_long, name != "cost"), aes(fill=name), position = position_dodge())+
scale_fill_manual(values = c("blue", "grey"))+
geom_line(data = filter(df_long, name == "cost"), aes( group = 1, color = name), size = 1)+
scale_color_manual(values = "red")+
#geom_text(data = filter(df_long, name == "cost"), size = 3,hjust=0, vjust=-0.5)+
geom_label(data = filter(df_long, name == "cost"), hjust=0, vjust=-0.5)+
scale_y_continuous(
name = "Sale and Share",
sec.axis = sec_axis(~., name ="Cost")
)+
theme_minimal()
plt1 <- ggplotly(plt, tooltip = c("value", "name", "model"))
for (i in 1:length(plt1$x$data)){
if (!is.null(plt1$x$data[[i]]$name)){
plt1$x$data[[i]]$name = gsub("\\(","",str_split(plt1$x$data[[i]]$name,",")[[1]][1])
}
}
plt1$x$layout$legend$title$text <- "name"

It looks like you've got some great information so far. This addresses all of the things you identified. Although, at this point, it would be a LOT easier to just make the plot in Plotly!
The first thing I did is comment out the call for geom_text and geom_label. Plotly doesn't tend to play well here. It is going back into the plot, but not here.
Next, I built your plot and looked at the names and legend groups that were assigned by the conversion. This doesn't change anything—this is just looking.
plt2 <- plotly_build(plt)
invisible(
lapply(1:length(plt2$x$data),
function(j) {
message(j, " ", plt2$x$data[[j]]$name, " & ",
plt2$x$data[[j]]$legendgroup)
})
)
# 1 (sale,1) & (sale,1)
# 2 (share,1) & (share,1)
# 3 (cost,1) & (cost,1)
#Quinten addressed this issue, but this is how you can just look. Once I saw what Plotly "made", I was sure I knew what I needed to change.
This code changes these strings. It also prints the update to the console so that you can inspect what you expect.
invisible(
lapply(1:length(plt2$x$data),
function(j) {
x <- plt2$x$data[[j]]$name # find the name
y <- str_extract(x, "[a-z]+") # remove anything that's not a letter
plt2$x$data[[j]]$name <<- y # put it back
plt2$x$data[[j]]$legendgroup <<- y
message(j, " ", plt2$x$data[[j]]$name, " & ",
plt2$x$data[[j]]$legendgroup)
})
)
# 1 sale & sale
# 2 share & share
# 3 cost & cost
You can use this sort of look/change/check to validate the information that ends up in the tooltips, as well. Instead of $name or $legendgroup, you'll look at $text.
This next chunk of code doesn't check the input and print it out (I figured that would be redundant). This just changes it. (I did use that process to build this though.)
tx = " "
invisible(
lapply(1:length(plt2$x$data),
function(k){
tx <<- plt2$x$data[[k]]$text # tooltip for each trace
lapply(1:length(tx),
function(m) {
tr <- strsplit(tx[[m]], "<br />") # tooltip for each point
tr2 <- unique(tr[[1]]) # remove redundancy
str <- paste0(tr2, collapse = "<br />")
tx[[m]] <<- str # put it back together
})
plt2$x$data[[k]]$text <<- tx # change the plot
})
)
Now on to the labels-if you want a background or border, you have to use annotations in Plotly. Like annotation in the ggplot package, annotations in Plotly has less 'rules' per se.
You have an odd order for the model, so that has to be addressed, as well. When data moves between ggplot and Plotly, things tend to be awry. So it's unlikely that you'd be able to connect to the original data.
One thing to keep in mind, I used paper space for the x-axis. The default paper space (domain) in Plotly is [0,1]. Your graph is evenly spaced along the x, with your values in the middle of each of the six categories, so everything on the x is in terms of 1/6th space.
So first, put the data in order as it needs to appear in the plot. Then add the annotations (labels) to the plot. I've also removed the name of the legend here.
# to add labels, we need to have the order the data appears on the plot
df2 <- df_long %>%
arrange(desc(value)) %>%
filter(name == "cost")
plt2 %>%
layout(legend = list(title = "")) %>% # remove legend name
add_annotations(x = c(1/12, 1/6 + 1/12, 1/3 + 1/12, # using domain for x-axis
1/2 + 1/12, 2/3 + 1/12, 5/6 + 1/12),
y = df2$value,
text = df2$value,
xshift = 20, # shift right 20 px
yshift = 15, # shift up 15 px
hoverinfo = "skip",
bgcolor = "white",
bordercolor = "black",
xref = "paper", yref = "y", # cat x, use domain for annot x
showarrow = F)
After all of that, here's your plot.
This is straight plotly. I think the labels would look a bit better with padding (which can be added).
df_long %>%
filter(name != "cost") %>%
plot_ly(x = ~model, y = ~value, color = ~name, type = "bar",
customdata = ~name, colors = c("blue", "gray"),
hovertemplate = paste0("Model: %{x}<br>Value: %{y}<br>",
"Name: %{customdata}<extra></extra>")) %>%
add_lines(inherit = F, data = df, x = ~model,
y = ~cost, color = I("red"),
name = "cost",
hovertemplate = paste0("Model: %{x}<br>Value: %{y}<br>",
"Name: cost<extra></extra>")) %>%
add_annotations(data = df, x = ~model, y = ~cost, text = ~cost,
bgcolor = "white", bordercolor = "black",
xshift = 15, yshift = 15, showarrow = F) %>%
layout(barmode = "group")
Pretty much the same as the converted plot.

Legend issue:
Using the code in this post: Strange formatting of legend in ggplotly in R . You can change the legend in ggplotly like this:
library(plotly)
myplot = ggplotly(plt)
for (i in 1:length(myplot$x$data)){
if (!is.null(myplot$x$data[[i]]$name)){
myplot$x$data[[i]]$name = gsub("\\(","",str_split(myplot$x$data[[i]]$name,",")[[1]][1])
}
}
myplot
Output:

Related

ggplot mirrored geom_bars customized colour

I am plotting max_temperature (mean_tmax) against rainfall (mean_rain) in a mirrored barplot: max temp displayed upwards, rain values downwards on the negative scale. These two are stored in the "name" variable.
To highlight the highest values out of the 32 years plotted, I created two vectors colVecTmax, colVecRain. They return a color vector of length 32 each, with the index of max values marked differently.
But when adding these two vectors to fill within geom_bar(), it turns out that ggplot stops counting the top after 16 bars, and moves down to the negative scale to continue. So it does not count by the name (mean_tmax, or mean_rain) variable.
This messes up the plot, and I am not sure how to get ggplot count through on the top bars for max_temperature first, coloring by colVecTmax, and then move down to do the same for rain on the negative scale with colVecRain.
Can anyone give a hint on how to solve this?
colVecTmax <- rep("orange",32)
colVecTmax[which.max(as.numeric(unlist(df.long[df.long$place=="sheffield" & df.long$name == "mean_tmax",4])))] <- "blue"
colVecRain <- rep("grey",32)
colVecRain[which.max(as.numeric(unlist(df.long[df.long$place=="sheffield" & df.long$name == "mean_rain",4])))] <- "blue"
ggplot(df.long[df.long$name %in% c('mean_rain', 'mean_tmax'), ] %>% filter(place== "sheffield")%>%
group_by(name) %>% mutate(value = case_when(
name == 'mean_rain' ~ value/10 * -1,
TRUE ~ value)) %>% mutate(place==str_to_sentence(placenames)) %>%
mutate(name = recode(name,'mean_rain' = "rainfall" , "mean_tmax" = "max temp"))
, aes(x = yyyy, y = value, fill=name))+
geom_bar(stat="identity", position="identity", fill=c(colVecTmax,colVecRain))+
labs(x="Year", y=expression("Rain in cm, temperature in ("*~degree *C*")"))+
geom_smooth(colour="black", lwd=0.5,se=F)+
scale_y_continuous(breaks = seq(-30, 30 , 5))+
scale_x_continuous(breaks = seq(1990, 2025, 5))+
guides(fill= guide_legend(title=NULL))+
scale_fill_discrete(labels=c("Max temperature", "Rainfall"))+
guides(fill=guide_legend(reverse=T), res=96)
Using ggplot2 there are much easier and less error prone ways to assign colors. Instead of creating color vectors which you pass to the color or fill argument you could simply map on aesthetics (which you basically already have done) and assign your desired colors using a manual scale, e.g. scale_fill_manual. The same approach works fine when you want to highlight some values. To this end you could create additional categories, e.g. in the code below I add "_max" to the name for the observations with the max temperature or rainfall and assign your desired "blue" color to these categories. As doing so will add additional categories I use the breaks argument of scale_fill_manual so that these max categories will not show up in the legend.
Using some fake random example data:
# Create example data
set.seed(123)
df.long <- data.frame(
name = rep(c("mean_rain", "mean_tmax"), each = 30),
place = "sheffield",
yyyy = rep(1991:2020, 2),
value = c(runif(30, 40, 100), runif(30, 12, 16))
)
library(ggplot2)
library(dplyr)
df_plot <- df.long %>%
filter(name %in% c("mean_rain", "mean_tmax")) |>
filter(place == "sheffield") %>%
mutate(value = case_when(
name == "mean_rain" ~ -value / 10,
TRUE ~ value
)) |>
# Maximum values
group_by(name) |>
mutate(name = ifelse(abs(value) >= max(abs(value)), paste(name, "max", sep = "_"), name))
ggplot(df_plot, aes(x = yyyy, y = value, fill = name)) +
geom_col(position = "identity") +
geom_smooth(colour = "black", lwd = 0.5, se = F) +
scale_y_continuous(breaks = seq(-30, 30, 5), labels = abs) +
scale_x_continuous(breaks = seq(1990, 2025, 5)) +
scale_fill_manual(
values = c(
mean_rain = "orange", mean_tmax = "grey",
mean_rain_max = "blue", mean_tmax_max = "blue"
),
labels = c(mean_tmax = "Max temperature", mean_rain = "Rainfall"),
breaks = c("mean_rain", "mean_tmax")
) +
labs(x = "Year", y = expression("Rain in cm, temperature in (" * ~ degree * C * ")"), fill = NULL) +
guides(fill = guide_legend(reverse = TRUE))

R Heatmap: conditionally change label text colours with (ggplot2 or plotly)

I am trying to produce a heatmap with ggplot2 or plotly in R, where the values associated with a block or tile are used as labels in the respective tile. This was not so difficult, but I have removed the legend and would like to change the colours of the labels conditional on their values to increase their visibility.
Here a reproducible examples to show what I mean.
Data (using data.table and dplyr):
sig <- rep(c("sig1", "sig2", "sig3"), 100, replace = TRUE, prob = c(0.4, 0.35, 0.25))
date <- c("2019-11-01", "2019-11-02", "2019-11-03")
another <- as.data.table(expand.grid(sig, date))
test_dat_numerics <- another[, number_ok := sample(0:100, 900, replace = TRUE)]
setnames(test_dat_numerics, c("Var1", "Var2"), c("sig", "date"))
test_dat_numerics <- test_dat_numerics[, avg := mean(number_ok), by = .(date, sig)] %>%
dplyr::select(-number_ok) %>%
dplyr::rename(number_ok = avg) %>%
dplyr::mutate(prop = ifelse(number_ok > 50, 1, 0))
dplyr::distinct()
The heatmap (with ggplot2):
ggp <- ggplot(test_dat_numerics, aes(date, sig, fill = number_ok)) +
geom_tile() +
geom_text(aes(label = test_dat_numerics$number_ok)) +
theme(legend.position="none")
This results in
The darker a block becomes the less visible the text becomes. To prevent this, my intention is to make the text white when a value is below 50 and black otherwise. This is the part where I failed both with ggplot2 and plotly until now and would be grateful for help.
With plotly:
p <- test_dat_numerics %>%
plot_ly(type = "heatmap",
x = ~date,
y = ~sig,
z = ~number_ok,
# zmax = 100,
# zmin = 0,
showscale = FALSE,
colorscale = "Blues") %>%
add_annotations(text = as.character(test_dat_numerics$number_ok),
showarrow = FALSE,
color = list(if (test_dat_numerics$number_ok[i] > 50) {"black"} else {"white"})) %>%
layout(title = "Test Heatmap",
# titlefont = t,
xaxis = list(title = "Datum"), yaxis = list(title = "Signal")
)
I found a great plotly example here, but I couldn't manage to get to work for my case. Here the annotation part of my code:
ann <- list()
for (i in 1:length(unique(test_dat_numerics$sig))) {
for (j in 1:length(unique(test_dat_numerics$date))) {
for (k in 1:(length(unique(test_dat_numerics$sig))*length(unique(test_dat_numerics$date)))) {
ann[[k]] <- list(
x = i,
y = j,
font = list(color = if (test_dat_numerics$number_ok[i] > 50) {"black"} else {"white"}),
text = as.character(test_dat_numerics$number_ok[[k]]),
xref = "x",
yref = "y",
showarrow = FALSE )
}
}
}
p_test_num_heat <- layout(p, annotations = ann)
Here, one of numerous attempts with ggplot2:
ggp <- ggplot(test_dat_numerics, aes(date, sig, fill = number_ok)) +
geom_tile() +
geom_text(aes(label = test_dat_numerics$number_ok)) +
geom_label(aes(colour = factor(test_dat_numerics$prop))) +
theme(legend.position="none")
(This code produces the plot in the image above if the second to last line is removed.)
I'm pretty stuck on this one... Thanks in advance for any advice!
With ggplot2, you can use colour in the aes of geom_text (+ scale_colour_manual):
ggplot(test_dat_numerics, aes(date, sig, fill = number_ok)) +
geom_tile() +
geom_text(aes(label = number_ok, colour =ifelse(number_ok>50, "black", "white"))) +
scale_colour_manual(values=c("white"="white", "black"="black")) +
theme(legend.position="none")

The mpg dataset in R

I am trying to figure out a way to color my point on a geom_point plot based upon the type of transmission, but in the mpg dataset, the trans column has different names for auto and manual trans. How can I rename the values in the trans column to be either Auto for automatic and Manual for manual transmissions? I also attached a picture of the desired graph for reference.
Here is my main plot code:
data <- mpg
n <- nrow(mpg)
mpg_auto <- subset(mpg, substring(trans[1:n],1,1)=="a")
mpg_manual <- subset(mpg, substring(trans[1:n],1,1)=="m")
mpg$trans <- factor(mpg$trans, levels=c(mpg_auto,mpg_manual),
labels = c("0","1"))
mpg_select <- subset(mpg, mpg$hwy > 30 & mpg$displ < 3)
mpg_select <- as.data.frame(mpg_select)
gg<- ggplot(mpg) + aes(x = displ, y = hwy) +
geom_point(aes(col = trans))+
geom_encircle(aes(x = displ, y = hwy),
data = mpg_select,
color= "darkgreen",
expand = .05,
size = 2) +
annotate_textp(x = .2, y = .9, size = 15,
label = "Efficient Vehicle", color = "darkgreen")+
labs(y = "Hwy MPG",
x = "Displacement")
ggMarginal(gg, type= "density", alpha = 0.5,
groupColour = TRUE, groupFill = TRUE)
Picture of the plot with the above code: https://ibb.co/fGMSXdn
Here's a good way to relabel the transmission (I create a new column named transmission, but you could just as easily overwrite the existing column).
mpg$transmission = ifelse(substring(mpg$trans, 1, 1) == "a", "automatic", "manual")
Now that's done, coloring is easy:
gg <- ggplot(mpg, aes(x = displ, y = hwy) +
geom_point(aes(color = transmission))+
labs(y = "Hwy MPG",
x = "Displacement")
I've left out all your non-standard ggplot stuff because I'm not sure what package(s) it's from. It doesn't seem related to your issue anyway, so you should be able to just add it back in.

ggpubr not creating multiple bars in ggdotchart

Utilizing the example package code in ggpubr, the ggdotchart function does not create separate segments as is shown in the example, instead there is only a single segment, though the dots seem to be placed in the correct orientation. Does anyone have any tips on what the problem may be? I've thought it may be due to factors, tibbles vs. df, but I haven't been able to determine the problem.
Code:
df <- diamonds %>%
filter(color %in% c("J", "D")) %>%
group_by(cut, color) %>%
summarise(counts = n())
ggdotchart(df, x = "cut", y ="counts",
color = "color", palette = "jco", size = 3,
add = "segment",
add.params = list(color = "lightgray", size = 1.5),
position = position_dodge(0.3),
ggtheme = theme_pubclean()
)
With the expected output of:
But instead I am getting:
Here is a way to get your desired plot without ggpubr::ggdotchart. The issue seems to be that geom_segment does not allow dodging, as discussed here: R - ggplot dodging geom_lines and here: how to jitter/dodge geom_segments so they remain parallel?.
# your data
df <- diamonds %>%
filter(color %in% c("J", "D")) %>%
group_by(cut, color) %>%
summarise(counts = n())
The first step is to expand your data. We will need this when we call geom_line which allows for dodging. I took this idea from #Stibu's answer. We create a copy of df and change the counts column to be 0 in df2. Finally we use bind_rows to create a single data frame from df and df2.
df2 <- df
df2$counts <- 0
df_out <- purrr::bind_rows(df, df2)
df_out
Then I use ggplot to create / replicate your desired output.
ggplot(df_out, aes(x = cut, y = counts)) +
geom_line(
aes(col = color), # needed for dodging, we'll later change colors to "lightgrey"
position = position_dodge(width = 0.3),
show.legend = FALSE,
size = 1.5
) +
geom_point(
aes(fill = color),
data = subset(df_out, counts > 0),
col = "transparent",
shape = 21,
size = 3,
position = position_dodge(width = 0.3)
) +
scale_color_manual(values = c("lightgray", "lightgray")) + #change line colors
ggpubr::fill_palette(palette = "jco") +
ggpubr::theme_pubclean()
There is an extra "group" argument you need!
df <- diamonds %>%
dplyr::filter(color %in% c("J", "D")) %>%
dplyr::group_by(cut, color) %>%
dplyr::summarise(counts = n())
ggdotchart(df, x = "cut", y ="counts",
color = "color", group="color", # here it is
palette = "jco", size = 3,
add = "segment",
add.params = list(color = "lightgray", size = 1.5),
position = position_dodge(0.3),
ggtheme = theme_pubclean()
)

R: Pie chart with percentage as labels using ggplot2

From a data frame I want to plot a pie chart for five categories with their percentages as labels in the same graph in order from highest to lowest, going clockwise.
My code is:
League<-c("A","B","A","C","D","E","A","E","D","A","D")
data<-data.frame(League) # I have more variables
p<-ggplot(data,aes(x="",fill=League))
p<-p+geom_bar(width=1)
p<-p+coord_polar(theta="y")
p<-p+geom_text(data,aes(y=cumsum(sort(table(data)))-0.5*sort(table(data)),label=paste(as.character(round(sort(table(data))/sum(table(data)),2)),rep("%",5),sep="")))
p
I use
cumsum(sort(table(data)))-0.5*sort(table(data))
to place the label in the corresponding portion and
label=paste(as.character(round(sort(table(data))/sum(table(data)),2)),rep("%",5),sep="")
for the labels which is the percentages.
I get the following output:
Error: ggplot2 doesn't know how to deal with data of class uneval
I've preserved most of your code. I found this pretty easy to debug by leaving out the coord_polar... easier to see what's going on as a bar graph.
The main thing was to reorder the factor from highest to lowest to get the plotting order correct, then just playing with the label positions to get them right. I also simplified your code for the labels (you don't need the as.character or the rep, and paste0 is a shortcut for sep = "".)
League<-c("A","B","A","C","D","E","A","E","D","A","D")
data<-data.frame(League) # I have more variables
data$League <- reorder(data$League, X = data$League, FUN = function(x) -length(x))
at <- nrow(data) - as.numeric(cumsum(sort(table(data)))-0.5*sort(table(data)))
label=paste0(round(sort(table(data))/sum(table(data)),2) * 100,"%")
p <- ggplot(data,aes(x="", fill = League,fill=League)) +
geom_bar(width = 1) +
coord_polar(theta="y") +
annotate(geom = "text", y = at, x = 1, label = label)
p
The at calculation is finding the centers of the wedges. (It's easier to think of them as the centers of bars in a stacked bar plot, just run the above plot without the coord_polar line to see.) The at calculation can be broken out as follows:
table(data) is the number of rows in each group, and sort(table(data)) puts them in the order they'll be plotted. Taking the cumsum() of that gives us the edges of each bar when stacked on top of each other, and multiplying by 0.5 gives us the half the heights of each bar in the stack (or half the widths of the wedges of the pie).
as.numeric() simply ensures we have a numeric vector rather than an object of class table.
Subtracting the half-widths from the cumulative heights gives the centers each bar when stacked up. But ggplot will stack the bars with the biggest on the bottom, whereas all our sort()ing puts the smallest first, so we need to do nrow - everything because what we've actually calculate are the label positions relative to the top of the bar, not the bottom. (And, with the original disaggregated data, nrow() is the total number of rows hence the total height of the bar.)
Preface: I did not make pie charts of my own free will.
Here's a modification of the ggpie function that includes percentages:
library(ggplot2)
library(dplyr)
#
# df$main should contain observations of interest
# df$condition can optionally be used to facet wrap
#
# labels should be a character vector of same length as group_by(df, main) or
# group_by(df, condition, main) if facet wrapping
#
pie_chart <- function(df, main, labels = NULL, condition = NULL) {
# convert the data into percentages. group by conditional variable if needed
df <- group_by_(df, .dots = c(condition, main)) %>%
summarize(counts = n()) %>%
mutate(perc = counts / sum(counts)) %>%
arrange(desc(perc)) %>%
mutate(label_pos = cumsum(perc) - perc / 2,
perc_text = paste0(round(perc * 100), "%"))
# reorder the category factor levels to order the legend
df[[main]] <- factor(df[[main]], levels = unique(df[[main]]))
# if labels haven't been specified, use what's already there
if (is.null(labels)) labels <- as.character(df[[main]])
p <- ggplot(data = df, aes_string(x = factor(1), y = "perc", fill = main)) +
# make stacked bar chart with black border
geom_bar(stat = "identity", color = "black", width = 1) +
# add the percents to the interior of the chart
geom_text(aes(x = 1.25, y = label_pos, label = perc_text), size = 4) +
# add the category labels to the chart
# increase x / play with label strings if labels aren't pretty
geom_text(aes(x = 1.82, y = label_pos, label = labels), size = 4) +
# convert to polar coordinates
coord_polar(theta = "y") +
# formatting
scale_y_continuous(breaks = NULL) +
scale_fill_discrete(name = "", labels = unique(labels)) +
theme(text = element_text(size = 22),
axis.ticks = element_blank(),
axis.text = element_blank(),
axis.title = element_blank())
# facet wrap if that's happening
if (!is.null(condition)) p <- p + facet_wrap(condition)
return(p)
}
Example:
# sample data
resps <- c("A", "A", "A", "F", "C", "C", "D", "D", "E")
cond <- c(rep("cat A", 5), rep("cat B", 4))
example <- data.frame(resps, cond)
Just like a typical ggplot call:
ex_labs <- c("alpha", "charlie", "delta", "echo", "foxtrot")
pie_chart(example, main = "resps", labels = ex_labs) +
labs(title = "unfacetted example")
ex_labs2 <- c("alpha", "charlie", "foxtrot", "delta", "charlie", "echo")
pie_chart(example, main = "resps", labels = ex_labs2, condition = "cond") +
labs(title = "facetted example")
It worked on all included function greatly inspired from here
ggpie <- function (data)
{
# prepare name
deparse( substitute(data) ) -> name ;
# prepare percents for legend
table( factor(data) ) -> tmp.count1
prop.table( tmp.count1 ) * 100 -> tmp.percent1 ;
paste( tmp.percent1, " %", sep = "" ) -> tmp.percent2 ;
as.vector(tmp.count1) -> tmp.count1 ;
# find breaks for legend
rev( tmp.count1 ) -> tmp.count2 ;
rev( cumsum( tmp.count2 ) - (tmp.count2 / 2) ) -> tmp.breaks1 ;
# prepare data
data.frame( vector1 = tmp.count1, names1 = names(tmp.percent1) ) -> tmp.df1 ;
# plot data
tmp.graph1 <- ggplot(tmp.df1, aes(x = 1, y = vector1, fill = names1 ) ) +
geom_bar(stat = "identity", color = "black" ) +
guides( fill = guide_legend(override.aes = list( colour = NA ) ) ) +
coord_polar( theta = "y" ) +
theme(axis.ticks = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text( colour = "black"),
axis.title = element_blank(),
plot.title = element_text( hjust = 0.5, vjust = 0.5) ) +
scale_y_continuous( breaks = tmp.breaks1, labels = tmp.percent2 ) +
ggtitle( name ) +
scale_fill_grey( name = "") ;
return( tmp.graph1 )
} ;
An example :
sample( LETTERS[1:6], 200, replace = TRUE) -> vector1 ;
ggpie(vector1)
Output

Resources