Showing data values on stacked bar chart in ggplot2












91















I'd like to show data values on stacked bar chart in ggplot2. Here is my attempted code



Year      <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4))
Category <- c(rep(c("A", "B", "C", "D"), times = 4))
Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251)
Data <- data.frame(Year, Category, Frequency)
library(ggplot2)
p <- qplot(Year, Frequency, data = Data, geom = "bar", fill = Category, theme_set(theme_bw()))
p + geom_text(aes(label = Frequency), size = 3, hjust = 0.5, vjust = 3, position = "stack")


enter image description here



I'd like to show these data values in the middle of each portion. Any help in this regard will be highly appreciated. Thanks










share|improve this question























  • Related question: stackoverflow.com/questions/18994631/…

    – Tyler Rinker
    Sep 25 '13 at 1:48











  • Not really the place for a debate, but I wonder if it's possible to be overly prescriptive about this, particularly for the more general audience. This is a nice example - numbers denote percentages that can be remembered, which removes the need for a scale that less numerically-literate readers might find less accessible?

    – geotheory
    Jan 20 '15 at 12:04


















91















I'd like to show data values on stacked bar chart in ggplot2. Here is my attempted code



Year      <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4))
Category <- c(rep(c("A", "B", "C", "D"), times = 4))
Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251)
Data <- data.frame(Year, Category, Frequency)
library(ggplot2)
p <- qplot(Year, Frequency, data = Data, geom = "bar", fill = Category, theme_set(theme_bw()))
p + geom_text(aes(label = Frequency), size = 3, hjust = 0.5, vjust = 3, position = "stack")


enter image description here



I'd like to show these data values in the middle of each portion. Any help in this regard will be highly appreciated. Thanks










share|improve this question























  • Related question: stackoverflow.com/questions/18994631/…

    – Tyler Rinker
    Sep 25 '13 at 1:48











  • Not really the place for a debate, but I wonder if it's possible to be overly prescriptive about this, particularly for the more general audience. This is a nice example - numbers denote percentages that can be remembered, which removes the need for a scale that less numerically-literate readers might find less accessible?

    – geotheory
    Jan 20 '15 at 12:04
















91












91








91


61






I'd like to show data values on stacked bar chart in ggplot2. Here is my attempted code



Year      <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4))
Category <- c(rep(c("A", "B", "C", "D"), times = 4))
Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251)
Data <- data.frame(Year, Category, Frequency)
library(ggplot2)
p <- qplot(Year, Frequency, data = Data, geom = "bar", fill = Category, theme_set(theme_bw()))
p + geom_text(aes(label = Frequency), size = 3, hjust = 0.5, vjust = 3, position = "stack")


enter image description here



I'd like to show these data values in the middle of each portion. Any help in this regard will be highly appreciated. Thanks










share|improve this question














I'd like to show data values on stacked bar chart in ggplot2. Here is my attempted code



Year      <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4))
Category <- c(rep(c("A", "B", "C", "D"), times = 4))
Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251)
Data <- data.frame(Year, Category, Frequency)
library(ggplot2)
p <- qplot(Year, Frequency, data = Data, geom = "bar", fill = Category, theme_set(theme_bw()))
p + geom_text(aes(label = Frequency), size = 3, hjust = 0.5, vjust = 3, position = "stack")


enter image description here



I'd like to show these data values in the middle of each portion. Any help in this regard will be highly appreciated. Thanks







r graphics ggplot2






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jul 11 '11 at 1:42









MYaseen208MYaseen208

7,94327100204




7,94327100204













  • Related question: stackoverflow.com/questions/18994631/…

    – Tyler Rinker
    Sep 25 '13 at 1:48











  • Not really the place for a debate, but I wonder if it's possible to be overly prescriptive about this, particularly for the more general audience. This is a nice example - numbers denote percentages that can be remembered, which removes the need for a scale that less numerically-literate readers might find less accessible?

    – geotheory
    Jan 20 '15 at 12:04





















  • Related question: stackoverflow.com/questions/18994631/…

    – Tyler Rinker
    Sep 25 '13 at 1:48











  • Not really the place for a debate, but I wonder if it's possible to be overly prescriptive about this, particularly for the more general audience. This is a nice example - numbers denote percentages that can be remembered, which removes the need for a scale that less numerically-literate readers might find less accessible?

    – geotheory
    Jan 20 '15 at 12:04



















Related question: stackoverflow.com/questions/18994631/…

– Tyler Rinker
Sep 25 '13 at 1:48





Related question: stackoverflow.com/questions/18994631/…

– Tyler Rinker
Sep 25 '13 at 1:48













Not really the place for a debate, but I wonder if it's possible to be overly prescriptive about this, particularly for the more general audience. This is a nice example - numbers denote percentages that can be remembered, which removes the need for a scale that less numerically-literate readers might find less accessible?

– geotheory
Jan 20 '15 at 12:04







Not really the place for a debate, but I wonder if it's possible to be overly prescriptive about this, particularly for the more general audience. This is a nice example - numbers denote percentages that can be remembered, which removes the need for a scale that less numerically-literate readers might find less accessible?

– geotheory
Jan 20 '15 at 12:04














2 Answers
2






active

oldest

votes


















145














From ggplot 2.2.0 labels can easily be stacked by using position = position_stack(vjust = 0.5) in geom_text.



ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
geom_bar(stat = "identity") +
geom_text(size = 3, position = position_stack(vjust = 0.5))


enter image description here



Also note that "position_stack() and position_fill() now stack values in the reverse order of the grouping, which makes the default stack order match the legend."





Answer valid for older versions of ggplot:



Here is one approach, which calculates the midpoints of the bars.



library(ggplot2)
library(plyr)

# calculate midpoints of bars (simplified using comment by @DWin)
Data <- ddply(Data, .(Year),
transform, pos = cumsum(Frequency) - (0.5 * Frequency)
)

# library(dplyr) ## If using dplyr...
# Data <- group_by(Data,Year) %>%
# mutate(pos = cumsum(Frequency) - (0.5 * Frequency))

# plot bars and add text
p <- ggplot(Data, aes(x = Year, y = Frequency)) +
geom_bar(aes(fill = Category), stat="identity") +
geom_text(aes(label = Frequency, y = pos), size = 3)


Resultant chart






share|improve this answer


























  • Thanks for this answer. I used it to do similar using data.table instead of plyr, so something like this: Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]

    – atomicules
    May 17 '12 at 15:49





















19














As hadley mentioned there are more effective ways of communicating your message than labels in stacked bar charts. In fact, stacked charts aren't very effective as the bars (each Category) doesn't share an axis so comparison is hard.



It's almost always better to use two graphs in these instances, sharing a common axis. In your example I'm assuming that you want to show overall total and then the proportions each Category contributed in a given year.



library(grid)
library(gridExtra)
library(plyr)

# create a new column with proportions
prop <- function(x) x/sum(x)
Data <- ddply(Data,"Year",transform,Share=prop(Frequency))

# create the component graphics
totals <- ggplot(Data,aes(Year,Frequency)) + geom_bar(fill="darkseagreen",stat="identity") +
xlab("") + labs(title = "Frequency totals in given Year")
proportion <- ggplot(Data, aes(x=Year,y=Share, group=Category, colour=Category))
+ geom_line() + scale_y_continuous(label=percent_format())+ theme(legend.position = "bottom") +
labs(title = "Proportion of total Frequency accounted by each Category in given Year")

# bring them together
grid.arrange(totals,proportion)


This will give you a 2 panel display like this:



Vertically stacked 2 panel graphic



If you want to add Frequency values a table is the best format.






share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f6644997%2fshowing-data-values-on-stacked-bar-chart-in-ggplot2%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    145














    From ggplot 2.2.0 labels can easily be stacked by using position = position_stack(vjust = 0.5) in geom_text.



    ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
    geom_bar(stat = "identity") +
    geom_text(size = 3, position = position_stack(vjust = 0.5))


    enter image description here



    Also note that "position_stack() and position_fill() now stack values in the reverse order of the grouping, which makes the default stack order match the legend."





    Answer valid for older versions of ggplot:



    Here is one approach, which calculates the midpoints of the bars.



    library(ggplot2)
    library(plyr)

    # calculate midpoints of bars (simplified using comment by @DWin)
    Data <- ddply(Data, .(Year),
    transform, pos = cumsum(Frequency) - (0.5 * Frequency)
    )

    # library(dplyr) ## If using dplyr...
    # Data <- group_by(Data,Year) %>%
    # mutate(pos = cumsum(Frequency) - (0.5 * Frequency))

    # plot bars and add text
    p <- ggplot(Data, aes(x = Year, y = Frequency)) +
    geom_bar(aes(fill = Category), stat="identity") +
    geom_text(aes(label = Frequency, y = pos), size = 3)


    Resultant chart






    share|improve this answer


























    • Thanks for this answer. I used it to do similar using data.table instead of plyr, so something like this: Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]

      – atomicules
      May 17 '12 at 15:49


















    145














    From ggplot 2.2.0 labels can easily be stacked by using position = position_stack(vjust = 0.5) in geom_text.



    ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
    geom_bar(stat = "identity") +
    geom_text(size = 3, position = position_stack(vjust = 0.5))


    enter image description here



    Also note that "position_stack() and position_fill() now stack values in the reverse order of the grouping, which makes the default stack order match the legend."





    Answer valid for older versions of ggplot:



    Here is one approach, which calculates the midpoints of the bars.



    library(ggplot2)
    library(plyr)

    # calculate midpoints of bars (simplified using comment by @DWin)
    Data <- ddply(Data, .(Year),
    transform, pos = cumsum(Frequency) - (0.5 * Frequency)
    )

    # library(dplyr) ## If using dplyr...
    # Data <- group_by(Data,Year) %>%
    # mutate(pos = cumsum(Frequency) - (0.5 * Frequency))

    # plot bars and add text
    p <- ggplot(Data, aes(x = Year, y = Frequency)) +
    geom_bar(aes(fill = Category), stat="identity") +
    geom_text(aes(label = Frequency, y = pos), size = 3)


    Resultant chart






    share|improve this answer


























    • Thanks for this answer. I used it to do similar using data.table instead of plyr, so something like this: Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]

      – atomicules
      May 17 '12 at 15:49
















    145












    145








    145







    From ggplot 2.2.0 labels can easily be stacked by using position = position_stack(vjust = 0.5) in geom_text.



    ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
    geom_bar(stat = "identity") +
    geom_text(size = 3, position = position_stack(vjust = 0.5))


    enter image description here



    Also note that "position_stack() and position_fill() now stack values in the reverse order of the grouping, which makes the default stack order match the legend."





    Answer valid for older versions of ggplot:



    Here is one approach, which calculates the midpoints of the bars.



    library(ggplot2)
    library(plyr)

    # calculate midpoints of bars (simplified using comment by @DWin)
    Data <- ddply(Data, .(Year),
    transform, pos = cumsum(Frequency) - (0.5 * Frequency)
    )

    # library(dplyr) ## If using dplyr...
    # Data <- group_by(Data,Year) %>%
    # mutate(pos = cumsum(Frequency) - (0.5 * Frequency))

    # plot bars and add text
    p <- ggplot(Data, aes(x = Year, y = Frequency)) +
    geom_bar(aes(fill = Category), stat="identity") +
    geom_text(aes(label = Frequency, y = pos), size = 3)


    Resultant chart






    share|improve this answer















    From ggplot 2.2.0 labels can easily be stacked by using position = position_stack(vjust = 0.5) in geom_text.



    ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
    geom_bar(stat = "identity") +
    geom_text(size = 3, position = position_stack(vjust = 0.5))


    enter image description here



    Also note that "position_stack() and position_fill() now stack values in the reverse order of the grouping, which makes the default stack order match the legend."





    Answer valid for older versions of ggplot:



    Here is one approach, which calculates the midpoints of the bars.



    library(ggplot2)
    library(plyr)

    # calculate midpoints of bars (simplified using comment by @DWin)
    Data <- ddply(Data, .(Year),
    transform, pos = cumsum(Frequency) - (0.5 * Frequency)
    )

    # library(dplyr) ## If using dplyr...
    # Data <- group_by(Data,Year) %>%
    # mutate(pos = cumsum(Frequency) - (0.5 * Frequency))

    # plot bars and add text
    p <- ggplot(Data, aes(x = Year, y = Frequency)) +
    geom_bar(aes(fill = Category), stat="identity") +
    geom_text(aes(label = Frequency, y = pos), size = 3)


    Resultant chart







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 21 '16 at 16:33









    Henrik

    42.2k994110




    42.2k994110










    answered Jul 11 '11 at 3:34









    RamnathRamnath

    44.3k10103135




    44.3k10103135













    • Thanks for this answer. I used it to do similar using data.table instead of plyr, so something like this: Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]

      – atomicules
      May 17 '12 at 15:49





















    • Thanks for this answer. I used it to do similar using data.table instead of plyr, so something like this: Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]

      – atomicules
      May 17 '12 at 15:49



















    Thanks for this answer. I used it to do similar using data.table instead of plyr, so something like this: Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]

    – atomicules
    May 17 '12 at 15:49







    Thanks for this answer. I used it to do similar using data.table instead of plyr, so something like this: Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]

    – atomicules
    May 17 '12 at 15:49















    19














    As hadley mentioned there are more effective ways of communicating your message than labels in stacked bar charts. In fact, stacked charts aren't very effective as the bars (each Category) doesn't share an axis so comparison is hard.



    It's almost always better to use two graphs in these instances, sharing a common axis. In your example I'm assuming that you want to show overall total and then the proportions each Category contributed in a given year.



    library(grid)
    library(gridExtra)
    library(plyr)

    # create a new column with proportions
    prop <- function(x) x/sum(x)
    Data <- ddply(Data,"Year",transform,Share=prop(Frequency))

    # create the component graphics
    totals <- ggplot(Data,aes(Year,Frequency)) + geom_bar(fill="darkseagreen",stat="identity") +
    xlab("") + labs(title = "Frequency totals in given Year")
    proportion <- ggplot(Data, aes(x=Year,y=Share, group=Category, colour=Category))
    + geom_line() + scale_y_continuous(label=percent_format())+ theme(legend.position = "bottom") +
    labs(title = "Proportion of total Frequency accounted by each Category in given Year")

    # bring them together
    grid.arrange(totals,proportion)


    This will give you a 2 panel display like this:



    Vertically stacked 2 panel graphic



    If you want to add Frequency values a table is the best format.






    share|improve this answer






























      19














      As hadley mentioned there are more effective ways of communicating your message than labels in stacked bar charts. In fact, stacked charts aren't very effective as the bars (each Category) doesn't share an axis so comparison is hard.



      It's almost always better to use two graphs in these instances, sharing a common axis. In your example I'm assuming that you want to show overall total and then the proportions each Category contributed in a given year.



      library(grid)
      library(gridExtra)
      library(plyr)

      # create a new column with proportions
      prop <- function(x) x/sum(x)
      Data <- ddply(Data,"Year",transform,Share=prop(Frequency))

      # create the component graphics
      totals <- ggplot(Data,aes(Year,Frequency)) + geom_bar(fill="darkseagreen",stat="identity") +
      xlab("") + labs(title = "Frequency totals in given Year")
      proportion <- ggplot(Data, aes(x=Year,y=Share, group=Category, colour=Category))
      + geom_line() + scale_y_continuous(label=percent_format())+ theme(legend.position = "bottom") +
      labs(title = "Proportion of total Frequency accounted by each Category in given Year")

      # bring them together
      grid.arrange(totals,proportion)


      This will give you a 2 panel display like this:



      Vertically stacked 2 panel graphic



      If you want to add Frequency values a table is the best format.






      share|improve this answer




























        19












        19








        19







        As hadley mentioned there are more effective ways of communicating your message than labels in stacked bar charts. In fact, stacked charts aren't very effective as the bars (each Category) doesn't share an axis so comparison is hard.



        It's almost always better to use two graphs in these instances, sharing a common axis. In your example I'm assuming that you want to show overall total and then the proportions each Category contributed in a given year.



        library(grid)
        library(gridExtra)
        library(plyr)

        # create a new column with proportions
        prop <- function(x) x/sum(x)
        Data <- ddply(Data,"Year",transform,Share=prop(Frequency))

        # create the component graphics
        totals <- ggplot(Data,aes(Year,Frequency)) + geom_bar(fill="darkseagreen",stat="identity") +
        xlab("") + labs(title = "Frequency totals in given Year")
        proportion <- ggplot(Data, aes(x=Year,y=Share, group=Category, colour=Category))
        + geom_line() + scale_y_continuous(label=percent_format())+ theme(legend.position = "bottom") +
        labs(title = "Proportion of total Frequency accounted by each Category in given Year")

        # bring them together
        grid.arrange(totals,proportion)


        This will give you a 2 panel display like this:



        Vertically stacked 2 panel graphic



        If you want to add Frequency values a table is the best format.






        share|improve this answer















        As hadley mentioned there are more effective ways of communicating your message than labels in stacked bar charts. In fact, stacked charts aren't very effective as the bars (each Category) doesn't share an axis so comparison is hard.



        It's almost always better to use two graphs in these instances, sharing a common axis. In your example I'm assuming that you want to show overall total and then the proportions each Category contributed in a given year.



        library(grid)
        library(gridExtra)
        library(plyr)

        # create a new column with proportions
        prop <- function(x) x/sum(x)
        Data <- ddply(Data,"Year",transform,Share=prop(Frequency))

        # create the component graphics
        totals <- ggplot(Data,aes(Year,Frequency)) + geom_bar(fill="darkseagreen",stat="identity") +
        xlab("") + labs(title = "Frequency totals in given Year")
        proportion <- ggplot(Data, aes(x=Year,y=Share, group=Category, colour=Category))
        + geom_line() + scale_y_continuous(label=percent_format())+ theme(legend.position = "bottom") +
        labs(title = "Proportion of total Frequency accounted by each Category in given Year")

        # bring them together
        grid.arrange(totals,proportion)


        This will give you a 2 panel display like this:



        Vertically stacked 2 panel graphic



        If you want to add Frequency values a table is the best format.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 14 '17 at 5:48









        DYZ

        27.8k62150




        27.8k62150










        answered Aug 9 '13 at 11:28









        AndrewMinCHAndrewMinCH

        52738




        52738






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f6644997%2fshowing-data-values-on-stacked-bar-chart-in-ggplot2%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

            How to fix TextFormField cause rebuild widget in Flutter