Seyma Kalay
Seyma Kalay

Reputation: 2863

Plot a wheel (pie) chart in R

I have a pie chart below, and I would like to create the wheel much more readable. many thanks in advance.

   library(ggplot2)
library(dplyr)

# Create Data
data <- data.frame(
  group=c("IMAGINE HERE I HAVE A LONG SURVEY QUESTIONS", 
          "AND THE TEXT IS IN DIFFERENT LENGTH", 
          "WANNA PLOT THESE IN ORDER", 
          "WITH 45 DEGREE ANGLE", 
          "PIE CAN BE PROPORTIONAL WITH THE TEXT LENGTH" ),
  value=c(13,7,9,21,2)
)

# Compute the position of labels
data <- data %>% 
  arrange(desc(group)) %>%
  mutate(prop = value / sum(data$value) *100) %>%
  mutate(ypos = cumsum(prop)- 0.5*prop )

# Basic piechart
ggplot(data, aes(x="", y=prop, fill=group)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  theme_void() + 
  theme(legend.position="none") +
  
  geom_text(aes(y = ypos, label = group), color = "white", size=6) +
  scale_fill_brewer(palette="Set1")

Upvotes: 0

Views: 310

Answers (3)

Quinten
Quinten

Reputation: 41603

It is not the best option, but you could use geom_label_repel from ggrepel like this:

library(ggplot2)
library(dplyr)
library(ggrepel)

data <- data %>% 
  arrange(desc(group)) %>%
  mutate(prop = value / sum(data$value) *100) %>%
  mutate(ypos = cumsum(prop)- 0.5*prop )

ggplot(data, aes(x="", y=prop, fill=group)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  theme_void() + 
  theme(legend.position="none") +
  geom_label_repel(data = data,
                   aes(y = ypos, label = group),
                   size = 4.5, nudge_x = 3, show.legend = FALSE) +
  scale_fill_brewer(palette="Set1")

Output:

enter image description here

Upvotes: 1

Rui Barradas
Rui Barradas

Reputation: 76673

Maybe to wrap the group text and have it plotted in many lines of text is a way to solve the problem.
First strwrap breaks each value in group, then paste inserts newline characters at the break points.

And the graphics device dimensions are made larger, though it doesn't show with reprex.

suppressPackageStartupMessages({
  library(ggplot2)
  library(dplyr)
})

# Create Data
data <- data.frame(
  group=c("IMAGINE HERE I HAVE A LONG SURVEY QUESTIONS", 
          "AND THE TEXT IS IN DIFFERENT LENGTH", 
          "WANNA PLOT THESE IN ORDER", 
          "WITH 45 DEGREE ANGLE", 
          "PIE CAN BE PROPORTIONAL WITH THE TEXT LENGTH" ),
  value=c(13,7,9,21,2)
)

# Compute the position of labels
data <- data %>% 
  arrange(desc(group)) %>%
  mutate(prop = value / sum(data$value) *100) %>%
  mutate(ypos = cumsum(prop) - 0.5*prop )

data$group2 <- sapply(data$group, \(x) {
  s <- strwrap(x, width = 15)
  paste(s, collapse = "\n")
})

old_par <- par()[c("fin", "mar")]
par(fin = old_par$fin + 5, mar = rep(0, 4))

# Basic piechart
ggplot(data, aes(x="", y=prop, fill=group)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  theme_void() + 
  theme(legend.position="none") +
  geom_text(aes(y = ypos, label = group2), color = "white", size=3) +
  scale_fill_brewer(palette="Set1")

par(old_par)

Created on 2022-05-29 by the reprex package (v2.0.1)

Upvotes: 3

Allan Cameron
Allan Cameron

Reputation: 174586

You have a better chance of fitting in the labels if you wrap them using str_wrap and curve them using geomtextpath:

# Compute the position of labels
data <- data %>% 
  arrange(desc(group)) %>%
  mutate(prop = value / sum(data$value) *100) %>%
  mutate(ypos = cumsum(prop)- 0.5*prop,
         group = stringr::str_wrap(group, 20))

library(geomtextpath)

# Basic piechart
ggplot(data, aes(x=1, y=prop, fill=group)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  theme_void() + 
  theme(legend.position="none") +
  geom_textpath(aes(x = 1.3, y = ypos, label = group,
                    vjust = group), color = "black", size = 6, 
                angle = 90) +
  scale_fill_brewer(palette="Set1") +
  scale_x_continuous(limits = c(0.5, 2)) +
  scale_vjust_manual(values = c(2, 1.8, 2.2, 2, 4))

enter image description here

Upvotes: 4

Related Questions