1

Most of the answers available refer to combining multiple ggplots together. I'm trying to generate multiple ggplots together. I have generated bar diagrams for multiple variables separately and then used 'ggarrange' to combine them together.

Create a sample dataset

y0 = c(1,0,1,1,0,1,0,1,1,0)
x1 = c("A","B","A","B","A","B","A","B","A","A")
x2 = c(1,2,2,1,1,2,2,1,2,2)
x3 = c("A","B","C","D","E","E","D","C","B","A")
df<- data.frame(y0,x1,x2,x3);
df

calculate statistics for x1 variable

x1_count <- df %>% 
group_by(x1) %>%
summarise(Count=n(), Num=sum(y0))  %>%
mutate(Rate=Num/Count*100.0)

generate ggplot for x1 vaiable

A<- ggplot(x1_count, aes(x=x1, y=Rate)) +
geom_bar(width=0.5, stat="identity") +
ggtitle('Rate by x1') +
xlab("x1") +
ylab("Rate (%)") +
theme(plot.title = element_text(hjust = 0.5),legend.position='bottom') 

calculate statistics for x2 variable

x2_count <- df %>% 
  group_by(x2) %>%
  summarise(Count=n(), Num=sum(y0))  %>%
  mutate(Rate=Num/Count*100.0)

generate ggplot for x2 vaiable

B<- ggplot(x2_count, aes(x=x2, y=Rate)) +
  geom_bar(width=0.5, stat="identity") +
  ggtitle('Rate by x2') +
  xlab("x2") +
  ylab("Rate (%)") +
  theme(plot.title = element_text(hjust = 0.5),legend.position='bottom') 
B

combine them together

figure1 <- ggarrange(A,B,ncol = 2, nrow = 1)
figure1

I'm trying to generate ggplots A and B, and the calculations associated with it together rather than doing it separately.

sayan de sarkar
  • 185
  • 1
  • 10
  • It seems like you might want to make a function that does the summarizing and plotting that you can then use in a loop, looping through the names of the variables and returning a list of plots. While simpler than what you are doing (since I didn't do any summarizing), I wrote up an example of making many plots using a function and `purrr::map()` loops [here](https://aosmith.rbind.io/2018/08/20/automating-exploratory-plots/) that you might find relevant. – aosmith Jul 31 '19 at 20:43

4 Answers4

2

You can create a function.

An R function has the following structure:

name <- function(argument) {
    what the function does
}

Considering that your plotting workflow is creating an additional variable and then plotting it, your could set your function argument to be the original dataframe df and then make the function do with it the dplyr and ggplot2 commands:

myfunction <- function(df) {
  # creating new variable
  x_count <- df %>% 
  group_by(x) %>%
  summarise(Count=n(), Num=sum(y0)) %>%
  mutate(Rate=Num/Count*100.0)

  # creating the plot
  plotX <- ggplot(x_count, aes(x=x, y=Rate)) +
  geom_bar(width=0.5, stat="identity") +
  ggtitle('Rate by x') +
  xlab("x") +
  ylab("Rate (%)") +
  theme(plot.title = element_text(hjust =     0.5),legend.position='bottom') 

  # showing the plot
  print(plotX)
}
Pau Insa
  • 53
  • 4
1

Consider a reshape of your data from wide to long (the preferred format of most analytical methods), then aggregate for Rate calculation and ggplot with facet_wrap:

reshape

rdf <- reshape(transform(df, x2 = as.character(x2)), 
               varying = list(names(df)[-1]), v.names = "Value",
               times = names(df)[-1], timevar = "Categ",
               new.row.names = 1:1E3, direction="long")
rdf

#    y0 Categ Value id
# 1   1    x1     A  1
# 2   0    x1     B  2
# 3   1    x1     A  3
# 4   1    x1     B  4
# 5   0    x1     A  5
# 6   1    x1     B  6
# 7   0    x1     A  7
# 8   1    x1     B  8
# 9   1    x1     A  9
# 10  0    x1     A 10
# 11  1    x2     1  1
# 12  0    x2     2  2
# 13  1    x2     2  3
# 14  1    x2     1  4
# 15  0    x2     1  5
# 16  1    x2     2  6
# 17  0    x2     2  7
# 18  1    x2     1  8
# 19  1    x2     2  9
# 20  0    x2     2 10
# 21  1    x3     A  1
# 22  0    x3     B  2
# 23  1    x3     C  3
# 24  1    x3     D  4
# 25  0    x3     E  5
# 26  1    x3     E  6
# 27  0    x3     D  7
# 28  1    x3     C  8
# 29  1    x3     B  9
# 30  0    x3     A 10

aggregate

agg_raw <- aggregate(y0 ~ Categ + Value, rdf, 
                    function(x) c(Num=sum(x), Count=length(x),
                                  Rate=sum(x)/length(x) * 100.00))
agg_df <- do.call(data.frame, agg_raw)
agg_df <- setNames(agg_df, gsub("y0.", "", names(agg_df)))
agg_df

#   Categ Value Num Count Rate
# 1    x1     A   3     6   50
# 2    x3     A   1     2   50
# 3    x1     B   3     4   75
# 4    x3     B   1     2   50
# 5    x2     1   3     4   75
# 6    x2     2   3     6   50
# 7    x3     C   2     2  100
# 8    x3     D   1     2   50
# 9    x3     E   1     2   50

ggplot + facet_wrap

ggplot(agg_df, aes(x=Value, y=Rate)) +
  geom_bar(width=0.5, stat="identity") +
  ggtitle('Rate by x1') +
  xlab("x1") +
  ylab("Rate (%)") +
  theme(plot.title = element_text(hjust = 0.5),legend.position='bottom') +
  facet_wrap(~Categ, ncol=2, scales="free_x")

Plot Output

Parfait
  • 104,375
  • 17
  • 94
  • 125
1

The excact same solution as Parfait but using more contemporary functions from the tidyverse

The data

library(tidyverse)
y0 = c(1,0,1,1,0,1,0,1,1,0)
x1 = c("A","B","A","B","A","B","A","B","A","A")
x2 = c(1,2,2,1,1,2,2,1,2,2)
x3 = c("A","B","C","D","E","E","D","C","B","A")
df<- data.frame(y0,x1,x2,x3)

reshape and aggregate

res<-
df %>% 
  tidyr::gather("Categ", "Value", x1, x2, x3) %>% 
  group_by(Categ, Value) %>% 
  summarise(Num=sum(y0),
            Count=length(y0),
            Rate=sum(y0)/length(y0) * 100.00)

Plot

  ggplot(res, aes(x=Value, y=Rate)) +
  geom_bar(width=0.5, stat="identity") +
  ggtitle('Rate by x1') +
  xlab("x1") +
  ylab("Rate (%)") +
  theme(plot.title = element_text(hjust = 0.5),legend.position='bottom') +
  facet_wrap(~Categ, ncol=2, scales="free_x")
Kresten
  • 1,758
  • 12
  • 18
1

If you are repeating the same task you can create a function where you simply need to place the values you want to calculate or graph into the function.

For your calculation you could:

counting <- function(variable(x1 or x2)){ 
df %>% 
  group_by{{variable}} %>% 
  mutate(Rate=Num/Count*100.0)}

Variable is where you put the specific variable of interest. Next you could create a function to generate a ggplot for each variable using the function above:

graphic <- function(variable){ 
 counting({{variable}}) %>%
 ggplot(aes(x = {{variable}}, y = Rate)) +
  geom_bar(width = 0.5, stat = "identity") +
  ylab("Rate (%)") +
  theme(plot.title = element_text(hjust = 0.5, 
        legend.postion = 'bottom')}

After doing that, you can then create a graphic for each variable by doing:

graphic(x1) +
 xlab("x1")

graphic(x2)

Hopefully this answers your question.

Edgar Zamora
  • 456
  • 3
  • 11