Single barplot from a list of similar tables in R

Viewed 68

Aim:

Say I have a dataframe as follows:

df<-data.frame(A=sample(1:5,20,replace=T),
               B=sample(1:5,20,replace=T),
               C=sample(1:5,20,replace=T),
               D=sample(1:5,20,replace=T))
#   A B C D
#1  1 5 4 1
#2  5 4 2 4
#3  3 1 2 1
#4  1 4 5 1
#5  5 3 3 4
#6  3 3 3 1
#7  1 1 2 1
#8  3 2 5 1
#9  5 3 4 3
#10 3 5 5 5
#11 3 4 1 4
#12 2 4 3 5
#13 5 5 5 2
#14 5 1 4 1
#15 2 3 1 4
#16 3 1 5 5
#17 2 3 5 1
#18 2 1 3 3
#19 5 3 1 4
#20 1 2 5 3

Now, I would like to plot a bar chart with the X-axis containing the categorical values 1,2,3,4,5 and the Y-axis as the frequency of the values for each of the columns A to D. Something like this: Bar-chart Screenshot

Better to mention, I want a single grouped barplot containing this.

What I tried:

I tried to create a table by applying the table command to each of the columns dataframe which gives me a list of tables.

freq<-sapply(df,table)
freq
#$A

#1 2 3 5 
#4 4 6 6 

#$B

#1 2 3 4 5 
#5 2 6 4 3 

#$C

#1 2 3 4 5 
#3 3 4 3 7 

#$D

#1 2 3 4 5 
#8 1 3 5 3

This gives me the required values for the table alright, but it provides that in a list.

Where am I stuck:

Well, I tried plotting the barplot by applying the barplot function to each list elements:

par(mfrow=c(2,2))
sapply(freq,barplot)
#$A
#     [,1]
#[1,]  0.7
#[2,]  1.9
#[3,]  3.1
#[4,]  4.3

#$B
#     [,1]
#[1,]  0.7
#[2,]  1.9
#[3,]  3.1
#[4,]  4.3
#[5,]  5.5

#$C
#     [,1]
#[1,]  0.7
#[2,]  1.9
#[3,]  3.1
#[4,]  4.3
#[5,]  5.5

#$D
#     [,1]
#[1,]  0.7
#[2,]  1.9
#[3,]  3.1
#[4,]  4.3
#[5,]  5.5

Barplot-1

Just as I had expected and as can be guessed from the picture above, I came across two problems in this group of graphs:

  • I cannot edit the attributes of the barplot (like colours of plots, main heading, etc.)
  • There are 4 individual plots instead of just 1 grouped barplot as I wanted at the beginning

The workaround for the first problem, as I found out after thinking a bit, is to just create a user-defined function and then passing that into sapply (but I cannot give the heading for my plots here, might have to think about that for a bit). A for-loop might be a better option here instead of sapply:

par(mfrow=c(2,2))
for(i in 1:length(freq))
{
    barplot(freq[[i]],main=names(freq)[i],col='Red')
}

Barplot-2

The problem:

However, I want only one grouped bar plot from this dataset, as I had mentioned in the beginning. But, it seems to me, that I cannot do it. I looked it up online, but couldn't get any satisfactory workarounds. A bit of help regarding this matter would be very much appreciated. Also, a hint, which involves only base R methods is preferred.

1 Answers

does this meet your wishes ? I used only base R functions.

df<-data.frame(A=sample(1:5,20,replace=T),
               B=sample(1:5,20,replace=T),
               C=sample(1:5,20,replace=T),
               D=sample(1:5,20,replace=T))

df2 <- as.data.frame(t(data.frame(sapply(df,table))))

df2$group <- rownames(df2)
rownames(df2) <- NULL

plotter_func <- function(x) barplot(x,beside = TRUE,legend.text = df2$group,col = c('red','white','blue','gray'))
par(mfrow=c(1,5))

plots <- apply(df2[-6],2,plotter_func)

enter image description here

Related