TikZ: How to put tables within arbitrarily placed nodes

nodestablestikz-pgf

I have several tables that are related to each other. Based on this question, I tried putting the table within a node within a matrix, but this constrains my tables to be arranged in an array. Since my tables do not naturally fit into an array, I need an alternative solution, but I have not been able to find one. Here's what I have so far:

\documentclass{article}

\usepackage{booktabs}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
  \matrix[ampersand replacement=\&] {
    \node (somenode) [shape=rectangle,fill=blue!20] at (0.0,0.0) {
      \begin{tabular}{lc} \toprule
        Name & Color  \\ \midrule
        A.N. Other & Blue \\
        J. Bloggs & Grey \\
        \bottomrule
      \end{tabular}
    }; \& 
    \node (somenode) [shape=rectangle,fill=orange!20] at (1.0,-2.0) {
      \begin{tabular}{lc} \toprule
        Name & Color  \\ \midrule
        A.N. Other & Blue \\
        J. Bloggs & Grey \\
        \bottomrule
      \end{tabular}
    };    
    \\
  };
\end{tikzpicture}

\end{document}

which produces:

enter image description here

What I need to do is:

  1. Position the tables arbitrarily,
  2. Draw arrows between the tables to indicate their relations,
  3. Have text directly above the table (as a sort of caption),

which would end up looking something like this (I've repeated the first table for simplicity but tables 3 and 4 would naturally be different):

enter image description here

Any pointers would be appreciated.

Best Answer

If you want to put the nodes at arbitrary places, why use a matrix? For example:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\usepackage{booktabs}

\begin{document}
\begin{tikzpicture}[]
    \node [shape=rectangle,fill=orange!20, align=center](table1) at (1.0,-2.0) {
            Caption for table \\
            \begin{tabular}{lc} \toprule
                Name & Color  \\ \midrule
                A.N. Other & Blue \\
                J. Bloggs & Grey \\
                \bottomrule
            \end{tabular}
        };
    \node [shape=rectangle,fill=blue!20, align=center](table2) at (6.0,-7.0) {
            Caption for table \\
            \begin{tabular}{lc} \toprule
                Name & Color  \\ \midrule
                A.N. Other & Blue \\
                J. Bloggs & Grey \\
                \bottomrule
            \end{tabular}
        };
    \draw [very thick, -Stealth] (table1) -- (table2);
\end{tikzpicture}

\end{document}

gives:

enter image description here

If you want the label without a background it is just a matter of putting two nodes one at the top of the other (using anchors is quite easy), and to avoid the arrows touching the boxes you can use either shorten > or an outer sep in the nodes.

For example, in the next code, I define a macro to position the tabular and its caption, and then I encompass them with a node which is the addressable one.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, fit}
\usepackage{booktabs}
% arguments are:  name caption content position color
\NewDocumentCommand\mytableat{m m +m m m}{%
    % main node, will contain the table
    \node [shape=rectangle,fill=#5, align=center](#1-t) at (#4) {
        \begin{tabular}{lc} \toprule
            #3
            \bottomrule
        \end{tabular}
    };
    \node [align=center, anchor=south](#1-c) at (#1-t.north) {#2};
    % this is the node encompassing both --- use inner sep to create
    % a white "space" around it
    \node [fit=(#1-t) (#1-c), inner sep=3mm](#1){};
}

\begin{document}
\begin{tikzpicture}[]
    \mytableat{table1}{caption for table 1}{%
                Name & Color  \\ \midrule
                A.N. Other & Blue \\
                J. Bloggs & Grey \\
        }{1, -2}{orange!20}
    \mytableat{table2}{caption for table 2}{%
                Name & Color  \\ \midrule
                A.N. Other & Blue \\
                J. Bloggs & Grey \\
        }{6, -7}{blue!20}
    \draw [very thick, -Stealth] (table1) -- (table2);
\end{tikzpicture}

\end{document}

enter image description here