1

I am writing a custom function to make pie charts with ggplot2. The code I have written works just fine, but when I start it using inside function body, it stops working. Any ideas why this might be happening?

dataframe <- as.data.frame(cbind(gender = c("male", "female", "female", "female", "male", "female", "male"),
                           pet = c("dog", "cat", "dog", "cat", "cat", "cat", "dog")))

library(dplyr)

## as standalone code

df <- dplyr::group_by_(dataframe, .dots = c('gender', 'pet')) %>%
  dplyr::summarize(counts = n()) %>%
  dplyr::mutate(perc = (counts / sum(counts)) * 100) %>%
  dplyr::arrange(desc(perc))

ggplot2::ggplot(df, aes('', counts)) +
  geom_col(position = 'fill', aes(fill = factor(pet))) +
  facet_wrap(~gender, labeller = "label_both") +
  geom_label(
    aes(label = paste0(round(perc), "%"), fill = factor(pet)),
    position = position_fill(vjust = 0.5),
    color = 'black',
    size = 5,
    show.legend = FALSE
  ) +
  coord_polar(theta = "y")

## as custom function

ggpiecustom <- function(data, condition, main) {

df <- dplyr::group_by_(data, .dots = c(condition, main)) %>%
  dplyr::summarize(counts = n()) %>%
  dplyr::mutate(perc = (counts / sum(counts)) * 100) %>%
  dplyr::arrange(desc(perc))

ggplot2::ggplot(df, aes('', counts)) +
  geom_col(position = 'fill', aes(fill = factor(main))) +
  facet_wrap(condition, labeller = "label_both") +
  geom_label(
    aes(label = paste0(round(perc), "%"), fill = factor(main)),
    position = position_fill(vjust = 0.5),
    color = 'black',
    size = 5,
    show.legend = FALSE
  ) +
  coord_polar(theta = "y")
}

ggpiecustom(data = dataframe, condition = 'gender', main = 'pet')

Created on 2018-01-19 by the reprex package (v0.1.1.9000).

Indrajeet Patil
  • 4,673
  • 2
  • 20
  • 51
  • Assign your ggplot object to a variable and then use `plot(variable)`. – VFreguglia Jan 19 '18 at 16:08
  • But the main problem is still ggplot2's strange evaluation rules. `fill` is still `factor(main)` and not the contents of `main` converted to a factor. – Bernhard Jan 19 '18 at 16:11
  • @Freguglia I did assign `ggplot` object to `p` and then used either `return(p)` or `plot(p)` inside custom function, but none of it worked. I get the same, unicolor plot. – Indrajeet Patil Jan 19 '18 at 16:11
  • 1
    The custom function is just trying to save you from a bad visualization choice. https://stackoverflow.com/questions/33594642/beautiful-pie-charts-with-r/33595456#33595456 – hrbrmstr Jan 19 '18 at 16:27

1 Answers1

2

The problem is ggplot is, inside your function, seeing factor('pet') and assigning the same value of pet for everyone. Use get(main) to specify you want the object with the name specified in main.

dataframe <- as.data.frame(cbind(gender = c("male", "female", "female", "female", "male", "female", "male"),
                                 pet = c("dog", "cat", "dog", "cat", "cat", "cat", "dog")))


ggpiecustom <- function(data, condition, main) {

  df <- dplyr::group_by_(data, .dots = c(condition, main)) %>%
    dplyr::summarize(counts = n()) %>%
    dplyr::mutate(perc = (counts / sum(counts)) * 100) %>%
    dplyr::arrange(desc(perc))

  ggplot2::ggplot(df, aes('', counts)) +
    geom_col(position = 'fill', aes(fill = factor(get(main)))) +
    facet_wrap(condition, labeller = "label_both") +
    geom_label(
      aes(label = paste0(round(perc), "%"), fill = factor(get(main))),
      position = position_fill(vjust = 0.5),
      color = 'black',
      size = 5,
      show.legend = FALSE
    ) +
    coord_polar(theta = "y")
}

ggpiecustom(data = dataframe, condition = 'gender', main = 'pet')
VFreguglia
  • 2,129
  • 4
  • 14
  • 35