How can I produce a MATLAB bar graph of categorical responses?

988 Views Asked by At

I have a 646x108 array of 646 student responses to 108 exam questions. It was a MCQ exam and all the responses are A, B, C, or D, so those letters are the contents of the cell array. I've been instructed to create a graph similar to the following one:

enter image description here

I was told that the 'bar' function would work. However, it would not work with the cell array.

I tried changing it to an array of double where A was converted to 1, B to 2, C to 3, D to 4. However, that still didn't work. It seemed to be not treating the responses as categorical, but averaging across the responses.

When I'm working in the cell format, the data looks like this:

enter image description here

In other words, on Q1 person 1 answered A, and person 2 answered B. On Q2 both students answered D.

When I converted that to double, the A became a 1, the B a 2, and so on.

1

There are 1 best solutions below

0
On BEST ANSWER

Try this. First I created some sample data, for 10 students answering 5 questions:

choices=['A' 'B' 'C' 'D'] %// I'll use this variable later as well
for m=1:10
    for n=1:5
        answers{m,n}=choices(randi(4));
    end
end
answers

Then to find the frequency of each answer to each question, freq, I looked at each response individually, and counted up how many students gave that answer to that question. That gives freq, an array with 4 rows (one for each possible answer) and 5 columns (one for each question).

freq=zeros(length(choices),size(answers,2));
for i=1:length(choices)
    freq(i,:)=sum(strcmp(answers,choices(i)));
end

Then to do the bar plot, you have to take the transpose of freq, and I divided it by the number of students so that the bars have height 1.

bar(freq.'/size(answers,1),'stack')
legend('A','B','C','D','Location','NorthEastOutside')

enter image description here

As a side note, freq can also be calculated without a for loop

freq=cell2mat(arrayfun(@(k) sum(strcmp(answers,choices(k))),1:length(choices),'UniformOutput',false).')

but it's not very readable or efficient.