Using org-table for qualifications using Emacs

Daniel Molina published on
6 min, 1026 words

By now no one will be surprised that I am a big fan of Emacs.

I use it more and more to correct students. It has great advantages:

In presentations (like this morning) I find it very comfortable to have the screen shared in a buffer the pdf (which I can open even if they sent it to me in zip) and in another the file with the comments.

But the most interesting thing is the grading, thanks to two great recent discoveries: qualifications with weights, orgaggregate.

I explain a bit how I use them.

Comments for each student

I have a section where I put comments for each student.

* Comments

** Student1

- P1: ...
- P2: ...
...

** Student2

- P1: ...
- P2: ...

Using this format I find it very convenient to move around. In addition, the part P1, ... I save it as a template and copy it for each student.

But the most interesting thing is the tables, I usually correct by weighting each test according to its score, and it comes in handy.

Scoring the students

I create a row for each student, and a column for each test, marking each box with a value between 0 and 1. 0 indicates totally wrong, 0.5 would be that I give half the score of the corresponding test, and 1 all the score.

For example, let's suppose three tests in which the final average would be that the first one is worth 3 points, the next one 4 and the third one another 3 points, I create the table as follows:

| Name     | Surname |  3 |    4 |  3 | Total |
|          |         | P1 |   P2 | P3 |       |
|----------+---------+----+------+----+-------|
| Surname1 | Name1   |  1 |  0.5 |  0 |   5.0 |
| Surname2 | Name2   |  0 | 0.75 |  1 |   6.0 |
| Surname3 | Name3   |  0 |    0 |  1 |   3.0 |
#+TBLFM: $6=vsum((@1$3..@1$5)*($3..$5));%.1f

The first row stores the score for each point, so that the final score can be automatically updated by changing both the weighting and the student grade (with C-c C-c). automatically updated by changing both the weighting and the student grade (with C-c C-c).

In https://orgmode.org/worg/org-tutorials/org-spreadsheet-lisp-formulas.html there is a good introduction to the use of formulas, which one day I will supplement 😊.

Tables can also be sorted, just put in the column to sort (like surname), and org-table-sort-lines to sort (, t s in spacemacs). There are two very useful approaches:

  • Sort alphabetically, such as put in the Surname column and after org-table-sort-lines select the a to sort alphabetically.

  • Sort by punctuation, as put in the Total column, and after org-table-sort-lines select the n to sort by punctuation.

Summary tables

A very convenient utility is the orgtbl-aggregate package that allows you to make summary tables in a very convenient way.

For example, if we wanted an additional table with only the final:

#+name: final
#+BEGIN: aggregate :table "groupE" :cols "Name Surname Total;'Qualification';%1f"
#+END:

As you can see, we mention an external table through its name (in #+name: ...) and list the columns we are interested in. columns we are interested in.

And by pressing C-c C-c in the begin, it is automatically completed:

#+BEGIN: aggregate :table "groupE" :cols "Name Surname Total;^N;'Qualification';%1f"
| Name     | Surname | Qualification |
|----------+---------+---------------|
| Surname2 | Name2   |           6.0 |
| Surname1 | Name1   |           5.0 |
| Surname3 | Name3   |           3.0 |
#+END:

As you can see you can also rename the attributes as shown in the example using the ; and italics. and the italics.

By changing the above table, you can run C-c C-c and it is automatically updated.

Filtering

You can also select. For example, if we want to show only the approved ones we can limit the search using :cond. search using :cond. In this case a little bit of emacs lisp is needed, but limiting the score is simple (just remember to convert the string to a number for comparison).

#+name: aprobados
#+BEGIN: aggregate :table "groupE" :cond(>= (string-to-number Total) 5.0):cols "Name Surname Total;'Qualification';%1f"
#+END:

With C-c C-c automatically completes the table:

#+name: pass
#+BEGIN: aggregate :table "groupE" :cond(>= (string-to-number Total) 5.0):cols "Name Surname Total;'Qualification';%1f"
| Name     | Surname | Qualification |
|----------+---------+---------------|
| Surname1 | Name1   |           5.0 |
| Surname2 | Name2   |           6.0 |
#+END:

Sorting summary tables

You can directly sort the summary tables using ^a for alphabetical, or ^n for numerical sorting (and ^A and ^N for descending sorting). numerically (and ^A and ^N for descending order).

#+BEGIN: aggregate :table :table "groupE" :cols "Name Surname Total;^N;'Rating';%1f"
#+END:

Which when pressing C-c C-c automatically completes the table:

#+BEGIN: aggregate :table :table "groupE" :cols "Name Surname Total;^N;'Rating';%1f"
| Name | Surname | Rating |
|------------+-----------+--------------|
| Surname2 | Name2 | 6.0 |
| Surname1 | Name1 | 5.0 |
| Surname3 | Name3 | 3.0 |
#+END:

Completing information

Let's fill in the original table with the number of students evaluated (row numbers), and the average of the grades:

  • Let's add the number of evaluations:

#+TBLFM: @>$2=vlen(@I..@II).

This line would add in the last row (@>) and second column ($2) the number of items. For not counting last names, you can add only the regions separated between two vertical lines (between @I and @II). (between @I and @II).

  • Averaging:

It is very easy to make an average row using vmean:

#+TBLFM: @>$6=vmean(@I$6..@II$6).

Combining it all:

#+name: groupE
| Name     | Surname |  3 |    4 |  3 | Total |
|          |         | P1 |   P2 | P3 |       |
|----------+---------+----+------+----+-------|
| Surname1 | Name1   |  1 |  0.5 |  0 |   5.0 |
| Surname2 | Name2   |  0 | 0.75 |  1 |   6.0 |
| Surname3 | Name3   |  0 |    0 |  1 |   3.0 |
|----------+---------+----+------+----+-------|
| Total    | 3       |    |      |    |  4.67 |
#+TBLFM: $6=vsum((@1$3..@1$5)*($3..$5));%.1f::@>$2=vlen(@I..@II)::@>$6=vmean(@I$6..@II$6);%.2f

Calculating data

Formulas can be added to the summary tables, and they are applied automatically.

I am going to make a table that indicates the passes, fails and pass ratio:

#+begin: aggregate :table "passed" :cols "count();'Passed' count();'Failed';%.0f count();'Ratio'"
| Pass | Fail | Ratio |
|------+------+-------|
|    2 |    1 |  66.7 |
#+TBLFM: $2=remote(groupE,@>$2)-$1::$3=$1/($1+$2)%; %.1f

I hope these tips have given you ideas on how to use Emacs and org-table to do cool stuff.