2

I want to concatenate two ascii tables (one below the other) that share some but not all column headings.

e.g.

Table 1

Head1 HeadA
1     a
2     b

Table 2

HeadA HeadFoo
c     bar

And the result would be

Head1 HeadA HeadFoo
1     a
2     b
c           bar

There is a babel library which does not quite do this, but it may have some helper functions (which I can't locate in emacs 24.5, but I guess I could copy paste the lisp into a file and read it).

Regarding the answers: Both Gastove and Tobias' answers work correctly. I chose Tobias only because it is more "pure".

2
  • Is converting your ascii tables to Org tables an option? Do you need an elisp solution, or could you pass both tables in to an org-babel block that spits out the combined result? If so, you could do this in R or Python (happy to post an answer showing how).
    – Gastove
    Apr 1, 2016 at 22:45
  • I worked on it a bit just now in a zsh script (stackoverflow.com/questions/36366948/…), so for this Q. i'm only interested in doing it in org-mode. I assumed I would convert to org tables and then convert back to ascii (cross that bridge when I get to it). That is, if you have a general non-emacs solution, post it on the other question :) Apr 1, 2016 at 22:47

2 Answers 2

1

I just add an emacs-lisp version to Gastove's answer. The code block is executed when you put point on the #+BEGIN_SRC line and input C-c C-c.

  Table 1
  #+name: first_tab
  | Head1 | HeadA |
  |     1 | a     |
  |     2 | b     |

  Table 2
  #+name: second_tab
  | HeadA | HeadFoo |
  | c     | bar     |

  #+BEGIN_SRC emacs-lisp :var first_tab=first_tab second_tab=second_tab
(require 'cl-lib)
(let ((combined-header (cl-union (car second_tab) (car first_tab) :test 'string-equal))
      (tbl-rearrange (lambda (new-header tab)
               (let ((old-header (car tab)))
             ;; TODO: Consider 'hline.
             (cl-loop
              for row in (cdr tab)
              collect (let ((alist (cl-mapcar 'cons old-header row)))
                    (mapcar
                     (lambda (col) (or (cdr (assoc col alist)) ""))
                     new-header)))))))
  (append
   (list combined-header)
   (funcall tbl-rearrange combined-header first_tab)
   (funcall tbl-rearrange combined-header second_tab)))
  #+END_SRC

  #+RESULTS:
  | Head1 | HeadA | HeadFoo |
  |     1 | a     |         |
  |     2 | b     |         |
  |       | c     | bar     |
2
  • Being new to org I don't really know how to execute this. It might help me and future readers to have some of the basic details about that. I've got it in an emacs buffer in (Evil)Org mode... tried various commands that fuzzy match "orc src" but not working yet. Got by doing "org-babel-execute-src-block-maybe" on the lisp block. Apr 2, 2016 at 9:40
  • @AlejandroErickson I do not know how key sequences are mapped by evil mode. In org mode most important things are done with the key sequence C-c C-c. The code block is executed when you put point on the #+BEGIN_SRC line and input C-c C-c. I add this to the answer.
    – Tobias
    Apr 2, 2016 at 11:18
1

My answer is an R-in-org-babel approach:

#+name: first_tab
| Head1 | HeadA |
|     1 | a     |
|     2 | b     |

#+name: second_tab
| HeadA | HeadFoo |
| c     | bar     |

#+BEGIN_SRC R :var a=first_tab b=second_tab :colnames t
  dfa <- data.frame(a)
  dfb <- data.frame(b)

  ## Get all names
  allnames <- union(names(dfa), names(dfb))

  addmissing <- function(df, namevec) {
    missing <- setdiff(namevec, names(df))
    for (n in missing) {
      df[, n] <- NA
    }
    return(df)
  }

  newdfa <- addmissing(dfa, allnames)
  newdfb <- addmissing(dfb, allnames)

  res <- rbind(newdfa, newdfb)

  return(res)
#+END_SRC

#+RESULTS:
| Head1 | HeadA | HeadFoo |
|-------+-------+---------|
|     1 | a     | nil     |
|     2 | b     | nil     |
|   nil | c     | bar     |
3
  • Looks good. I'll test tomorrow if I can get R working via MacPorts. Will accept in a day or two. Apr 1, 2016 at 23:24
  • You could do something comparable in Python with Pandas, if it's easier; you can even do this in elisp with a little gumption.
    – Gastove
    Apr 1, 2016 at 23:33
  • ... or you can do this in elisp if it is easier;-).
    – Tobias
    Apr 2, 2016 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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