Blog‎ > ‎

R Result Analysis - Preparing the Data

posted Jun 17, 2019, 3:19 PM by MUHAMMAD MUN`IM AHMAD ZABIDI   [ updated Jul 20, 2019, 11:06 PM ]
This post is the first of two posts on using R for student data analysis. I explored using R because there were more than 300 students from all sections for the SKEE2263 course. Using Excel on Mac/Windows was fine, but LibreOffice on Ubuntu choked due to the sheer number of data rows.

For the SKEE2263 course, the breakdown of marks is as follows:

  Tests
 Final  Milestones 1-3  Milestones 4-6
 CLO1  20  50    
 CLO2      15  
 CLO3        15

For analysis using R, first prepare a comma-separated values (CSV) file containing the student name, matric number, tests score, final score, milestone 1-3 score, milestone 4-6 score, academic program and section. All the scores are normalized according to the table above. Modify the number of fields and scores according to your course as required.

Commands that you enter is in blue. The command head skee2263-allsections.csv  displays the first three lines of the CSV file in Linux/Mac. For Windows, you can use Notepad to look inside the file.

$ head skee2263-allsections.csv
name,matric,tests,final,mile1,mile4,prog,sect
STUDENT 1,MATRIC1,9.1,31.5,14.25,15,2SKEE,1
STUDENT 2,MATRIC2,12.35,22.5,13,9.25,2SKEE,1

R can also import Excel files but combining CSV files downloaded from iOBE is probably easier compared to combining data from different Excel files. Just make sure to clean up the extra commas before joining the files.

For analysis, go into R, preferably using Rstudio. Or Visual Studio.

Install dplyr (if not already installed) and import it.

> install.packages(pkgs="dplyr")
> library(dplyr)

Read in the data file.

> my=read.csv("altera.csv")

Dump all data:

> my

Or just show the first 6 lines:

> head(my)

       name    matric tests final mile1 mile4  prog sect
1 student 1 MATRIC001  9.10  31.5 14.25 15.00 2SKEE    1
2 student 2
MATRIC002 12.35  22.5 13.00  9.25 2SKEE    1
3 student 3
MATRIC003 11.55  38.0 14.25 10.75 2SKEE    1
4 student 4
MATRIC004 11.60  28.0 14.25 10.75 2SKEE    1
5 student 5
MATRIC005  8.25  20.0 10.00 14.79 2SKEE    1
6 student 6
MATRIC006 15.30  38.5 15.00 15.00 2SKEE    1

Make a table or two:

> table(my$prog)

1SKEE 1SKEL 1SKEM 2SKEE 2SKEL 2SKEM 3SKEM 4SKEL 4SKEM
    3     8     4   128   126    72     1     1     1

> xtabs(~ prog + sect, my)
       sect
prog     1  2  3  4  5  6  7  8  9 10 11 12 13
  1SKEE  0  0  1  0  1  0  0  0  0  0  0  1  0
  1SKEL  0  1  0  0  0  4  0  0  0  0  1  2  0
  1SKEM  1  0  0  0  0  0  0  0  0  0  0  3  0
  2SKEE 26 27 27 26 22  0  0  0  0  0  0  0  0
  2SKEL  0  0  1  1  0 27 20 14 28 30  0  5  0
  2SKEM  2  0  1  5  0  0  0  0  0  0 26  6 32
  3SKEM  0  1  0  0  0  0  0  0  0  0  0  0  0
  4SKEL  0  0  0  0  0  1  0  0  0  0  0  0  0
  4SKEM  0  0  1  0  0  0  0  0  0  0  0  0  0

Create a total column

> my$total <- my$tests + my$final +my$mile1 + my$mile4
> my$total <- round(my$total)
> head(my,2)

       name    matric tests final mile1 mile4  prog sect total
1 student 1 MATRIC001  9.10  31.5 14.25 15.00 2SKEE    1    70
2 student 2
MATRIC002 12.35  22.5 13.00  9.25 2SKEE    1    57

Create the passfail column (optional):

> my$passfail <- ifelse(my$total < 40, "fail", "pass")

> head(my,2)

       name    matric tests final mile1 mile4  prog sect total passfail
1 student 1 MATRIC001  9.10  31.5 14.25 15.00 2SKEE    1    70     pass
2 student 2
MATRIC002 12.35  22.5 13.00  9.25 2SKEE    1    57     pass

Create the grade column:

> my$grade <- ifelse(my$total < 30, "E", ifelse(my$total<35, "D-", ifelse(my$total<40, "D", ifelse(my$total<45, "D+", ifelse(my$total<50, "C-", ifelse(my$total<55,"C", ifelse(my$total<60, "C+", ifelse(my$total<65, "B-", ifelse(my$total<70, "B", ifelse(my$total<75, "B+", ifelse(my$total<80, "A-", ifelse(my$total<90, "A", "A+"))))))))))))

Delete the passfail column, where 10 is the column number starting from 1 (do this only if you created this column):

> my <- my[,-10]

> head(my,2)

       name    matric tests final mile1 mile4  prog sect total grade
1 student 1 MATRIC001  9.10  31.5 14.25 15.00 2SKEE    1    70    B+
2 student 2
MATRIC002 12.35  22.5 13.00  9.25 2SKEE    1    57    C+

Generate a couple of cross tables:

> xtabs(~ grade + sect, my)
     sect
grade  1  2  3  4  5  6  7  8  9 10 11 12 13
   A   6  7  6  7  3 10  4  2  5  6  8  4  5
   A-  6  5  4  3  4  1  6  1  1  2  2  3  4
   A+  2  0  4  0  1 12  0  0  8  9 10  0  2
   B   3  2  1 10  4  2  1  3  4  3  1  3  5
   B-  2  4  1  3  3  1  3  5  1  3  3  5  6
   B+  2  7  6  4  4  2  1  1  5  5  2  1  2
   C   3  1  2  1  2  3  3  1  1  1  0  0  4
   C-  0  0  3  0  0  0  0  0  0  1  0  0  0
   C+  5  3  4  4  1  1  1  1  2  0  1  1  1
   D+  0  0  0  0  0  0  1  0  1  0  0  0  3
   E   0  0  0  0  1  0  0  0  0  0  0  0  0


> xtabs(~ grade + prog, my)
     prog
grade 1SKEE 1SKEL 1SKEM 2SKEE 2SKEL 2SKEM 3SKEM 4SKEL 4SKEM
   A      0     1     1    24    26    21     0     0     0
   A-     2     0     1    20    12     6     1     0     0
   A+     0     0     0     7    28    12     0     1     0
   B      0     2     1    18    13     8     0     0     0
   B-     0     4     0    11    16     9     0     0     0
   B+     0     1     0    23    13     5     0     0     0
   C      0     0     0     8     9     5     0     0     0
   C-     0     0     0     2     1     0     0     0     1
   C+     0     0     1    15     6     3     0     0     0
   D+     0     0     0     0     2     3     0     0     0
   E      1     0     0     0     0     0     0     0     0


The previous table can also be generated using:

> table(my$grade, my$sect)

Another interesting table is the grade summary table:

> table(my$grade)

 A A- A+  B B- B+  C C- C+ D+  E
73 42 48 42 40 42 22  4 25  5  1


The data frame is filtered to remove failures and new data frame called x is created.

> x = my[my$total >=40,]
> table(x$grade)

 A A- A+  B B- B+  C C- C+ D+
73 42 48 42 40 42 22  4 25  5

The second part of this post is continued in R Result Analysis - Simple Reporting.

Comments