I am glad it helped, I wiil try
to do what you would like to achieve:

but I am humble R learner and beginner as well, so maybe we will see if @technocrat can help when he wakes up ? :slight_smile:

regards,
Andrzej

1 Like

Please have a look at this:

df <- structure(list(modality = structure(c(1L, 2L, 3L, 5L, 4L), .Label = c("Appearance", 
 "Aroma", "Flavor", "Hedonic", "Texture"), class = "factor"), 
     First_response = c(201L, 8L, 107L, 151L, 282L), Second_response = c(72L, 
     17L, 148L, 225L, 260L), Third_response = c(54L, 17L, 177L, 
     220L, 360L), Fourth_response = c(46L, 24L, 168L, 198L, 356L
     ), Fifth_response = c(39L, 13L, 122L, 150L, 402L), Frequency = c(749L, 
     722L, 828L, 792L, 726L)), class = "data.frame", row.names = c(NA, 
 -5L))

library(reshape2)

library(ggplot2)

library(tidyverse)
#> Warning: package 'tidyr' was built under R version 4.0.0


df2 <- select(df, -Frequency)

dat <- melt(df2)
#> Using modality as id variables

ggplot(dat, aes(variable, value, fill=interaction(modality))) +
  geom_bar(stat='identity', position='dodge') +
  theme_bw() + theme(axis.text.x = element_text(angle=90, hjust=1)) +
  scale_fill_brewer('Variables', palette='Spectral') + geom_text(aes(label=value), position=position_dodge(width=0.9), vjust=-0.25) +
  theme(legend.position="bottom")

Created on 2020-04-07 by the reprex package (v0.3.0)

I am still working on how to add percentages on Y axis.

regards,
Andrzej

1 Like

Thanks for the help and I appreciate your effort.
I do not need data points as such on top of each bar when y axis is frequency. Can we change axis title "value" to "Frequency". Also, please delete word variable.

In mean time I was trying to learn font size change, legend position change, color change etc.

Thanks a lot!

Here you are:

ggplot(dat, aes(variable, value, fill=interaction(modality))) +
  geom_bar(stat='identity', position='dodge') +
  theme_bw() + theme(axis.text.x = element_text(angle=90, hjust=1)) +
  scale_fill_brewer('Variables', palette='Spectral') + geom_text(aes(label=value), position=position_dodge(width=0.9), vjust=-0.25) +
  theme(legend.position="bottom")+
  theme(legend.title=element_blank()) +
xlab("") + ylab("Frequency")

and without bars' labels:

ggplot(dat, aes(variable, value, fill=interaction(modality))) +
  geom_bar(stat='identity', position='dodge') +
  theme_bw() + theme(axis.text.x = element_text(angle=90, hjust=1)) +
  scale_fill_brewer('Variables', palette='Spectral') + 
  theme(legend.position="bottom")+
  theme(legend.title=element_blank()) +
xlab("") + ylab("Frequency")

kind regards,
Andrzej

2 Likes

Wow! Thanks for the great regexp Only very mild tweaks to be 100% cut-and-paste. 2020 to date award winner for qualifying heats!

1 Like

Here's an example of how to build up the color, font, position changes step by step. I'm not recommending how the OP choose a presentation style, just for the process of building up.

1 Like

Thanks for the example and regxp, but I am still wondering how I can have percentage on secondary axis. Its kind of "one data but I want 2 axis". One side it should have % axis and Frequency on secondary axis. @Andrzej helped me to have one primary axis, but secondary axis is still far from reality.

Thanks

1 Like

Yes, it is possible to have two axes, such as kg and pounds but those are simply different scales for the same aspect of the same quantity. Count and frequency can't work the same way. Using frequency (count/total) for y reflects a different aspect than just count.

In tabulations by category this is often addressed as a weighted average emphasizing the cumulative contribution.

Okay, but percentage was calculated from frequency, so technically it should be related.

1 Like

Well, yes it's related, true. I'm having trouble dredging this out of school maths 60 years ago, but consider whether both are on the same measurement scale type

Got it. Yes, they are not on same scale.
Actually, I first tried this in excel and came to know that I cant do this in excel. But when I contacted excel help they said that they do this for me but they were charging for this. So I thought that R would be better place for me to look for and actually this way I shall start learning it. So, definitely there should be a way to change the table into %age (based on frequency) and put axis as secondary axis (associate %age with frequency), if excel people can do this. Anyway, I learned a lot.

Thanks

I may have missed a bit here and am just going off the last bit of code. Is there a reason why the x axis labels need to be vertical?

ggplot(dat, aes(variable, value, fill=interaction(modality))) +
  geom_bar(stat='identity', position='dodge') +
  theme_bw() + 
  scale_fill_brewer('Variables', palette='Spectral') + geom_text(aes(label=value), position=position_dodge(width=0.9), vjust=-0.25) +
  theme(legend.position="bottom")+
  theme(legend.title=element_blank()) +
  labs(x = NULL, y = "Frequency")

1 Like

How I can move legend into the graph. I know this function:
theme(legend.position = c(x,.y)
but how it would work when we have just y axis

Can you show a drawing like you did before regarding what do you want to get ?

The main thing was to have 2 axis, percent and frequency on primary and secondary axis. But because it seems not possible I am just playing with my graph. But here is a drawing where I had everything in percentage.

The x and y refer to the legend position on the graph. Just play around with the numbers.

For example:

ggplot(dat, aes(variable, value, fill=interaction(modality))) +
  geom_bar(stat='identity', position='dodge') +
  theme_bw() + 
  scale_fill_brewer('Variables', palette='Spectral') + geom_text(aes(label=value), position=position_dodge(width=0.9), vjust=-0.25) +
  theme(legend.title=element_blank()) +
  labs(x = NULL, y = "Frequency") +
  theme(legend.position = c(.3, .95),legend.direction = "horizontal")

1 Like

Hi @andresrcs, I have read your solution in this post:
https://community.rstudio.com/t/adding-percentages-to-a-bargraph-in-ggplot/35860

but I am still confsed how to convert counts to percentages in this plot.
Can you advise, please ?

Thanks for the extended effort. I shall go through it later today.
Otherwise, If you divide column response by frequency column, you should be able to get %. Like, first response has 201 count for appearance and if you divide it by frequency column 749, its percent (27%). Similar to other columns.
Thanks a lot!
Annotation 2020-04-09 085700

1 Like

Making the conversion on the data is trivial, the challenge would be to get a primary y-axis with frequency and a secondary y-axis with percentages, I don't know how to do it or if it's possible with ggplot2, I think you can do it with base R and lattice but I don't remember how.

library(tidyverse)

df <- data.frame(
   First_response = c(201L, 8L, 107L, 151L, 282L),
  Second_response = c(72L, 17L, 148L, 225L, 260L),
   Third_response = c(54L, 17L, 177L, 220L, 360L),
  Fourth_response = c(46L, 24L, 168L, 198L, 356L),
   Fifth_response = c(39L, 13L, 122L, 150L, 402L),
        Frequency = c(749L, 722L, 828L, 792L, 726L),
         modality = as.factor(c("Appearance",
                                "Aroma","Flavor","Texture","Hedonic"))
)

df %>% 
    mutate_at(vars(-modality, - Frequency), ~ . / Frequency) %>% 
    gather(Response, Percentage, First_response:Fifth_response) %>%
    mutate(Response = factor(Response,
                      levels = c("First_response", "Second_response",
                                 "Third_response", "Fourth_response",
                                 "Fifth_response"))) %>% 
    ggplot(aes(x = Response, y = Percentage, fill = modality)) +
    geom_col(position = "dodge") + 
    geom_text(aes(label = scales::percent(Percentage,
                                          accuracy = 0.1)),
              position = position_dodge(width=0.9),
              vjust = -0.25) +
    labs(x = NULL, y = "Percentage") +
    scale_y_continuous(labels = scales::label_percent()) +
    scale_fill_brewer('Variables', palette='Spectral') +
    theme_bw() + 
    theme(legend.title = element_blank(),
          legend.position = c(.3, .95),
          legend.direction = "horizontal")

1 Like

Thank you very much indeed @andresrcs for your kind reply and help.
I learned a lot and now I will try to figure something out to have both y-axises.

2 Likes