[Tex/LaTex] Color table with data from csv file with colors from csv file

colorcsvexternal filestables

I am trying to create a table (which is from a csv file) which cells are colored (from another csv file (this way I can do preprocessing externally)). I have looked briefly at tools such as datatool, csvsimple, and pgfplotstable, and searched through many other questions but have not encountered an answer which allows coloring from an external file reading data from an external file. 1 describes coloring each element of a table using static data individually using logic/commands within the file. 2 explains dynamic coloring using logic within the file, but does not read color, however does not color reading color from an external file.

The desired result is, given a m by n (6×6 in this example) csv file as the following

 ,1,2,3,4,5
1,1,2,3,4,5
2,2,4,6,8,10
3,3,6,9,12,15
4,4,8,12,16,20
5,5,10,15,20,25

as well as a m by n color file, a m by n table where the (i,j) entry of the table contains the (i,j) entry of the data csv file, colored according to the (i,j) entry of the color csv file. The colors in the csv file can be in whatever format is most convenient for the tool which ends up being used, although ideally it would be able to specify shades and colors (perhaps via hex RGB or RGBA), however even just specifying the xcolor by name would work fine.

An examples of potential preprocessing would be using an external python script to read in the data csv file, normalizing all the data, and applying some sort of color palette to the normalized data, and writing the corresponding color value to the color csv file.

Any and all help is greatly appreciated, thank you very much!

Edit1: Provided further description for why the previous two questions do not answer this one, as well as provide example of preprocessing.

Best Answer

An expl3 implementation.

Items in both csv files are stored in property lists, in the form <row>@<column>, emulating a two-dimensional array. Then a token list variable is built from the data so retrieved, where each cell contains

\__aerys_colortable_color:n { <color> } <item>

where the function is a wrapper around \cellcolor.

\begin{filecontents*}{\jobname-data.csv}
0,1,2
1,1,2
2,2,4
\end{filecontents*}

\begin{filecontents*}{\jobname-colors.csv}
gray!20,[rgb]{0.1,0.3,0.9},green!20
[RGB]{201,123,12},[cmyk]{0.1,0.9,0.2,0.4},green
red,yellow!49,green
\end{filecontents*}

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\makecolortable}{mm}
 {% #1 = data file, #2 = colors file
  \aerys_colortable:nn { #1 } { #2 }
 }

\ior_new:N \g__aerys_colortable_data_ior
\int_new:N \l__aerys_colortable_row_int
\int_new:N \l__aerys_colortable_column_int
\prop_new:N \l__aerys_colortable_data_prop
\prop_new:N \l__aerys_colortable_colors_prop
\tl_new:N \l__aerys_colortable_body_tl
\seq_new:N \l__aerys_colortable_temp_seq

\cs_generate_variant:Nn \prop_put:Nnn { Ne }
\cs_generate_variant:Nn \prop_item:Nn { Ne }

\cs_new_protected:Nn \aerys_colortable:nn
 {
  \int_zero:N \l__aerys_colortable_column_int
  % store the data
  \__aerys_colortable_read:Nn \l__aerys_colortable_data_prop { #1 }
  % store the colors
  \__aerys_colortable_read:Nn \l__aerys_colortable_colors_prop { #2 }
  % get the number of columns
  \ior_open:Nn \g__aerys_colortable_data_ior { #1 }
  \ior_map_inline:Nn \g__aerys_colortable_data_ior
   {
    \int_set:Nn \l__aerys_colortable_column_int { \clist_count:n { ##1 } }
    \ior_map_break:
   }
  \ior_close:N \g__aerys_colortable_data_ior
  % fill the table
  \tl_clear:N \l__aerys_colortable_body_tl
  \int_step_inline:nn { \l__aerys_colortable_row_int }
   {
    \int_step_inline:nn { \l__aerys_colortable_column_int - 1 }
     {
      \tl_put_right:Nx \l__aerys_colortable_body_tl
       {
        \aerys_colortable_color:n
         {
          \prop_item:Nn \l__aerys_colortable_colors_prop { ##1 @ ####1 }
         }
        \prop_item:Nn \l__aerys_colortable_data_prop { ##1 @ ####1 }
        &
       }
     }
    \tl_put_right:Nx \l__aerys_colortable_body_tl
     {
      \aerys_colortable_color:n 
       {
        \prop_item:Ne \l__aerys_colortable_colors_prop { ##1 @ \int_to_arabic:n { \l__aerys_colortable_column_int } }
       }
      \prop_item:Ne \l__aerys_colortable_data_prop { ##1 @ \int_to_arabic:n { \l__aerys_colortable_column_int } }
      \exp_not:N \\
     }
   }
  \begin{tabular}{*{\l__aerys_colortable_column_int}{c}}
  \tl_use:N \l__aerys_colortable_body_tl
  \end{tabular}
 }

\cs_new_protected:Nn \__aerys_colortable_read:Nn
 {
  \int_zero:N \l__aerys_colortable_row_int
  \prop_clear:N #1
  \ior_open:Nn \g__aerys_colortable_data_ior { #2 }
  \ior_map_inline:Nn \g__aerys_colortable_data_ior
   {
    \int_incr:N \l__aerys_colortable_row_int
    \seq_set_split:Nnn \l__aerys_colortable_temp_seq { , } { ##1 }
    \seq_indexed_map_inline:Nn \l__aerys_colortable_temp_seq
     {
      \prop_put:Nen #1 { \int_to_arabic:n { \l__aerys_colortable_row_int } @ ####1 } { ####2 }
     }
   }
  \ior_close:N \g__aerys_colortable_data_ior
 }

\cs_new_protected:Nn \aerys_colortable_color:n
 {
  \str_if_eq:eeTF { [ } { \tl_head:n { #1 } }
   {
    \cellcolor#1
   }
   {
    \cellcolor{#1}
   }
 }

\ExplSyntaxOff

\begin{document}

\makecolortable{\jobname-data.csv}{\jobname-colors.csv}

\end{document}

enter image description here

Related Question