0

This question is equally on graphic design as it is on an efficient implementation via LaTeX.

I would like to visualize several aligned string columns. These columns are to be read from top to bottom and may occasionally contain blank fields. The alignment must - obviously - not be broken, and the individual strings should remain readable.

COL1 COL2 COL3
foo  foo  foo
bar  bar  bar
baz       baz
qux  qux     
     quux quux

What would be an efficient way to visualize these columns in TEX?

Here is an example via ASCII, where the strings are boxed up and the boxes connected by vertical lines.

 ---      ---      --- 
|foo|    |foo|    |foo|
 ---      ---      --- 
  |        |        |  
 ---      ---      --- 
|bar|    |bar|    |bar|
 ---      ---      --- 
  |        |        |  
 ---       |       --- 
|baz|      X      |baz|
 ---       |       --- 
  |        |        |  
 ---      ---       | 
|qux|    |qux|      X
 ---      ---       | 
  |        |        |  
  |       ---      --- 
  X      |quux|   |quux|
          ---      --- 
2

Since you think of these as columns, I'm assuming you'd rather input your strings column by column rather than row by row. One way to do this is using the forest package:

\documentclass[tikz, border=5pt]{standalone}

\usepackage{forest}
\forestset{%
  my columns/.style={%
    for descendants={rectangle, draw}, 
    for children={no edge}, 
    phantom, s sep=1cm,
  },
  % Pick one of these styles
  hidden empty nodes/.style={%
    delay={%
      where content={}{%
        shape=coordinate,
      }{},
    },
  },
  x empty nodes/.style={%
    delay={%
      where content={}{%
        content=\textsf{x}, draw=none
      }{},
    },
  },
}
\begin{document}

\begin{forest} my columns, hidden empty nodes [
  [foo [bar [baz [qux []]]]]
  [foo [bar [ [qux [quxx]]]]]
  [foo [bar [baz [ [quxx]]]]]
  ]
\end{forest}

\begin{forest} my columns, x empty nodes [
  [foo [bar [baz [qux []]]]]
  [foo [bar [ [qux [quxx]]]]]
  [foo [bar [baz [ [quxx]]]]]
  ]
\end{forest}

\end{document}

hidden empty nodes              x empty nodes

Of course, forest seems like a bit of overkill in this situation, and leaves you with a slightly odd notation in the source...

EDIT: To make the empty nodes use bullets instead of xs, you can replace content=\textsf{x} with content=\textbullet. In this case you might want to also set inner sep=0 for empty nodes so that the line touches the bullet. On the other hand, it might be easier to just draw the node as a filled circle, as I've done in the example below.

To add column headers one option is to add a label to the first node in each column, like [foo, label={Col 1} [bar [baz [qux []]]]]. In this case you can control the distance between the header and the first node by setting, e.g., \tikzset{label distance=1em}. On the other hand, if you want to write the column header first you could just remove the box and edge from the first node in each column. The resulting code looks like

\documentclass[tikz, border=5pt]{standalone}

\usepackage{forest}
\forestset{%
  my columns/.style={%
    for descendants={
      rectangle, draw,
      anchor=center, % vertically align (empty) nodes at the middle
      font=\strut, % make the box size independent of ascenders/descenders
      l sep=0em, % make the level height independent of box height
    },
    for children={no edge,
      draw=none, inner sep=0pt, outer sep=0pt, font={}, % style of column header
      for children={no edge,
        l=2em, % header distance (minimum 1em)
      }
    },
    phantom, % hide the root node
    s sep=1cm, % distance between columns
    bullet empty nodes
  },
  bullet empty nodes/.style={%
    delay={%
      where content={}{%
        circle, inner sep=.5mm, fill, font={}
        % draw=none, content=\textbullet, font={}, inner sep=-1pt,
      }{},
    },
  },
}
\begin{document}

\begin{forest} my columns [
  [Col 1 [foo [bar [baz [qux []]]]]]
  [Col 2 [foo [bar [ [qux [bar]]]]]]
  [Col 3 [foo [bar [baz [ [quxx]]]]]]
  ]
\end{forest}

\end{document}

bullet empty nodes

Here I've also added some things to make it so that ascenders and descenders (or lack thereof) don't change the heights of the boxes and so that the empty nodes add the same height to their columns as non-empty nodes (even though the empty node itself is smaller than a non-empty node).

2
  • Excellent, this is exactly what I was looking for! However, I would need two minor adjustments that I cannot get to work: (a) How would I add column headers (i.e., COL1, COL2, COL3)? (b) I cannot replace the x denoting missing elements with a symbol, such as \bullet (i.e., content=\bullet, draw=none). – Michael G Nov 14 '16 at 11:12
  • @MichaelGruenstaeudl I've edited the solution above to (hopefully) address these requests. – Emma Nov 15 '16 at 5:19
1

One possible way is to define a macro.

Code:

\documentclass{amsart}
\usepackage{etoolbox}
\newcommand{\example}[3] {
  $\boxed{{\sim\text{#1}\sim}}$&$\boxed{{\sim\text{#2}\sim}}$&$\boxed{{\sim\text{#3}\sim}}$\\\|&\|&\|\\}
\newcommand{\finish}[3] {
  $\boxed{{\sim\text{#1}\sim}}$&$\boxed{{\sim\text{#2}\sim}}$&$\boxed{{\sim\text{#3}\sim}}$}
\begin{document}
\Huge
\begin{tabular}{c c c}
COL1&COL2&COL3\\
\example{foo}{foo}{foo}
\example{bar}{bar}{bar}
\example{baz}{}{baz}
\example{qux}{qux}{}
\finish{}{quux}{quux}
\end{tabular}
\end{document}

This gives:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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