Tables and Org Mode Code Blocks

I have lots of Org files that collect data and have an embedded code block to generate a summary table. Here are a couple of examples that others may find useful. The first thing to know is that tables are stored as a list of rows with each row being a list of the row’s elements. If we think of a table as an m \times n matrix, the table is stored as

\begin{matrix}
((T_{1,1} T_{1,2} \cdots T_{1,n})
(T_{2,1} T_{2,2} \cdots T_{2,n})
\cdots
(T_{m,1} T_{m,2} \cdots T_{m,n}))
\end{matrix}

It’s pretty easy to build a table from scratch and make it the output of a code block. As a simple example, suppose you have a long table of 3 columns that tracks data over time. You don’t want to export the whole table when you output the document because a lot of the data is old and not that interesting anymore. Let’s suppose that the table is named (via #+NAME:) “data-table”. Here is a code block to output the last 3 entries.

#+BEGIN_SRC emacs-lisp :var tab=data-table :exports results :results table
  (cons '("Col. 1" "Col. 2" "Col. 3") (cons 'hline (last tab 3)))
#+END_SRC

The (last tab 3) generates a list of the last 3 rows. The two cons’s put the header and horizontal line on the front of the table. The result is

Col. 1 Col. 2 Col. 3
1 2 3
4 5 6
7 8 9

As a second example, suppose we want to use the entire input table for our calculations. Org mode is especially intelligent about this. By default, if you have a header (indicated by the horizontal line), Org will remove the header before sending the table to your code block. It’s Emacs so of course that’s configurable. You can control what happens to the header with the :colnames header argument but most of the time you’ll want the default action.

Now suppose we want to build a summary table containing the low and high values of columns 2 and 3. We can do something like

#+BEGIN_SRC emacs-lisp :var tab=data-table :exports results :results table
  (let (col2-low col2-high col3-low col3-high)
    ;; routine calculations to set col1-low, etc.
    `((" " "Low" "High") hline
      ("Col. 2" ,col2-low ,col2-high)
      ("Col. 3" ,col3-low ,col3-hi)))
#+END_SRC

Assuming the Low and High values are as shown, the last quasiquoted expression is output as the table

  Low High
Col. 2 2 8
Col. 3 3 9

The nice thing is that the “routine calculations” don’t have to worry about the header when accessing the data; it’s as if it didn’t exists.

This entry was posted in General and tagged , . Bookmark the permalink.
  • Heikki Lehvaslaiho

    Not having done table evaluations in elisp before, I took your "routine calculations" as a challenge. Filtering the smallest value from a column turned out to be easier than I expected with dash.el functions: (setq col2-low (-min (-select-column 1 tab )))

  • Daniel Doherty

    I find myself using tables frequently in my day job, so I wrote a ruby gem for operating on tables as objects. It includes methods for reading and writing tables as arrays of arrays, which I use frequently to get tables in and out of org-mode files in emacs. If anyone is interested in trying it out, it's at https://github.com/ddoherty03/fat_table.