2

I found here in the org manual how to output from an org-babel source-code block to an org-mode table, namely through something like

#+header :results output table

I have had some trouble getting org-mode to interpret separator rows in output correctly, however, Here is an example

  #+name: stack_overflow_mve
  #+header: :exports results
  #+header: :results output table
  #+begin_src C++ :noweb yes :results output :flags -std=c++14 :includes '(<algorithm> <functional> <iostream> <cmath> <string.h> <stdio.h> <stdlib.h> <iomanip>)"
    double means   [] {0.23, 0.77,     2.05,    3.8,   6.35};
    double stddevs [] {0,    0.763675, 2.28184, 3.965, 6.65608};
    size_t total_count = sizeof(means) / sizeof(means[0]);
    std::cout << "count " << "mean " << "std_dev" << std::endl;
    std::cout << "-----|" << "----|" << "------|" << std::endl;
    for (size_t count = 0; count < total_count; ++count) {
        std::cout << count + 1      << " ";
        std::cout << means[count]   << " ";
        std::cout << stddevs[count] << " " << std::endl;
    }
  #+end_src

The code block above produces the following almost-table. As you can see, the separators on the second line are not correct. That incorrectness hinders my ability to feed the table to some later code blocks without manual intervention.

  #+RESULTS: stack_overflow_mve
  | count | mean |  std_dev |
  | ----- | ---- |   ------ |
  |     1 | 0.23 |        0 |
  |     2 | 0.77 | 0.763675 |
  |     3 | 2.05 |  2.28184 |
  |     4 |  3.8 |    3.965 |
  |     5 | 6.35 |  6.65608 |

If I put the cursor inside the table on the second line, replace the first space with a - and press TAB, org-mode corrects it to the following:

  | count | mean |  std_dev |
  |-------+------+----------|
  |     1 | 0.23 |        0 |
  |     2 | 0.77 | 0.763675 |
  |     3 | 2.05 |  2.28184 |
  |     4 |  3.8 |    3.965 |
  |     5 | 6.35 |  6.65608 |

Of course, I want to do that with my code so that my document is fully automated. Here are a bunch of attempts, each of which produces some hilariously differently wrong results:

//std::cout << "|-----+-----+-----|" << std::endl;
//std::cout << "|-----|-----|-----|" << std::endl;
//std::cout << "-----\t" << "---- \t" << "------" << std::endl;
//std::cout << "----- " << "---- " << "------ " << std::endl;
//std::cout << "------" << "-----" << "-------" << std::endl;

I was unable to find specific info in the org-manual about how to format separator lines correctly from org-babel code.

1
  • 1
    Have you tried the :colnames header argument? Some of the ob libraries support a list as an argument, i.e. :colnames '("count" "mean" "std_dev") in your case.
    – mutbuerger
    Commented May 18, 2017 at 16:02

2 Answers 2

4

Some (most?) ob libraries take a list as an argument for the :colnames header:

#+begin_src elisp :colnames '("Key" "Value")
(list '("a" 43) '("b" 87))
#+end_src

#+results:
| Key | Value |
|-----+-------|
| a   |    43 |
| b   |    87 |
1
  • Note that if there is an input table and an output table, then they must both have the same :colnames orgmode.org/manual/colnames.html#colnames . I don't know a solution for inputs and outputs that have different column names.
    – Reb.Cabin
    Commented May 18, 2017 at 19:42
0

I found an answer that addresses the following problem: with :colnames, an input table must have the same column names as the output table, lest you get an error like this

: error: cannot initialize an array element of type 'const char *' with an rvalue of type 'double'
const char* data_header[1] = {0.23};
                              ^~~~
1 error generated.

But :results output raw verbatim lets you format a table nicely. Here is a full example:

#+NAME: a_little_data
|  0.23 |
|  1.31 |
|  4.61 |
|  9.05 |
| 16.55 |

# nope! #+header: :colnames '("count" "mean" "stddev")
#+header: :results output raw verbatim
#+header: :flags=c++14
#+header: :includes '(<iostream> <cmath>)"
#+begin_src C++ :var data=a_little_data
    double sum    = 0;
    double sumsqr = 0;
    double * running_mean   = new double [data_rows];
    double * running_stddev = new double [data_rows];
    for (size_t i = 0; i < data_rows; ++i) {
        running_mean  [i] = 0;
        running_stddev[i] = 0;
    }
    for (size_t i = 0; i < data_rows; ++i) {
        size_t count = i + 1;
        sum += data[i][0];
        sumsqr += (data[i][0] * data[i][0]);
        running_mean[i] = (sum / count);
        double mean = running_mean[i];
        if (count != 1) {
            running_stddev[i] = std::sqrt
                ( (sumsqr - count * mean * mean) /
                  (count - 1) );
        }
    }
    std::cout << "| count " << "| mean " << "| stddev"  << std::endl;
    std::cout << "|--"  << std::endl;
    for (size_t i = 0; i < data_rows; ++i) {
        std::cout << "| " << i + 1             << " ";
        std::cout << "| " << running_mean[i]   << " ";
        std::cout << "| " << running_stddev[i] << " " << std::endl;
    }
    delete [] running_mean;
    delete [] running_stddev;
#+end_src

#+RESULTS:
| count | mean |   stddev |
|-------+------+----------|
|     1 | 0.23 |        0 |
|     2 | 0.77 | 0.763675 |
|     3 | 2.05 |  2.28184 |
|     4 |  3.8 |    3.965 |
|     5 | 6.35 |  6.65608 |

Not the answer you're looking for? Browse other questions tagged or ask your own question.