Search code examples
functiongridwolfram-mathematicatabular

Create a Function for Customized Tabular Representation


I use the code below get an overview of parts of my data.

  • What would be the best way to make a function out of the below code ?

  • It would take a dataList as well as some graphical options (such as colors) as arguments and return a customized tabular representation as shown below.

    overviewtheData=Text@Grid[{Map[Rotate[Text[#],
    90Degree]&,data[[1]]]}~Join~data[[2;;]],
    Background->{{{{White,Pink}},{1->White}}},
    Dividers->{All,{1->True,2->True,0->True}},
    ItemSize->{1->5,Automatic},
    Alignment->Top,
    Frame->True,
    FrameStyle->Thickness[2],
    ItemStyle->{Automatic,Automatic,{{1,1},
    {1,Length@data[[1]]}}->Directive[FontSize->15,Black,Bold]}]
    

enter image description here


Solution

  • Belisarius gave the basic method. I shall introduce an advanced method, because you seem eager to learn.

    First let me say that I saw what I believed were simplifications to your code, and I made them, hopefully not in error.

    I will use this sample data in illustrations below:

    data = Prepend[
             RandomInteger[99, {5, 12}], 
             DateString[{1, #}, "MonthName"] & /@ Range@12
           ];
    

    Goals

    1. Since the main function used is Grid it makes sense to allow passing options to it.

    2. You have a series of options that define your table. I want to be able to conveniently change these.

    3. I want the possibility of custom options not understood by Grid.


    Implementation

    Goal #1

    An argument pattern opts:OptionsPattern[] is added, which matches any sequence of Option -> Setting arguments, and names it opts. (See: OptionsPattern for more.) Then, opts is inserted into the basic function before the other options for Grid. This allows any explicitly given options to override the defaults, or new ones to be given.

    customTabular[data_, opts : OptionsPattern[]] :=
      Grid[MapAt[Rotate[#, 90 Degree] & /@ # &, data, 1],
       opts,
       Background -> {{{White, Pink}}},
       Dividers -> {All, {2 -> True}},
       ItemSize -> {1 -> 5},
       Alignment -> {Center, {1 -> Top}},
       Frame -> True,
       FrameStyle -> Thickness[2],
       ItemStyle -> Directive[FontSize -> 15, Black, Bold]
      ] // Text
    

    Examples:

    customTabular[data]
    

    enter image description here

    customTabular[data, Background -> LightBlue]
    

    enter image description here

    Goal #2

    The options that define your tabular format can be separated from the function body. This will allow them to be conveniently changed or referenced. I start by clearing the previous definition with ClearAll. Then I set default Options for customTabular:

    ClearAll[customTabular]
    
    Options[customTabular] =
      {Background -> {{{White, Pink}}},
       Dividers -> {All, {2 -> True}},
       ItemSize -> {1 -> 5},
       Alignment -> {Center, {1 -> Top}},
       Frame -> True,
       FrameStyle -> Thickness[2],
       ItemStyle -> Directive[FontSize -> 15, Black, Bold]};
    

    Now the function proper. Here Options@customTabular gets the rules given above.

    customTabular[data_, opts : OptionsPattern[]] := 
     Grid[MapAt[Rotate[#, 90 Degree] & /@ # &, data, 1],
       opts, 
       Sequence @@ Options@customTabular
     ] // Text
    

    Now you can easily change the defaults with SetOptions. Example:

    SetOptions[customTabular, 
      Background -> {{{LightMagenta, LightOrange}}}
    ];
    
    customTabular[data]
    

    enter image description here

    Goal #3

    Now I want to add an option that is not passed to Grid. I choose "Rotation" to change the text rotation of the title row.

    Again I clear the prior definition and the default options. Notice the inclusion of "Rotation" -> 90 Degree in the list.

    ClearAll[customTabular]
    
    Options[customTabular] =
      {Background -> {{{White, Pink}}},
       Dividers -> {All, {2 -> True}},
       ItemSize -> {1 -> 5},
       Alignment -> {Center, {1 -> Top}},
       Frame -> True,
       FrameStyle -> Thickness[2],
       ItemStyle -> Directive[FontSize -> 15, Black, Bold],
       "Rotation" -> 90 Degree};
    

    Now I need a way to use this new option, and I need a way to keep this option from being sent to Grid:

    • I access the option with OptionValue which will give the default if none is explicitly given.

    • I pass only valid Grid options by using FilterRules.

    I first join any explicit options to the front of the Options@customTabular list, again to override defaults.

    customTabular[data_, opts : OptionsPattern[]] :=
     Grid[MapAt[Rotate[#, OptionValue["Rotation"]] & /@ # &, data, 1],
       Sequence @@ FilterRules[{opts} ~Join~ Options@customTabular, Options@Grid]
     ] // Text
    

    Example:

    SetOptions[customTabular, Background -> {{{LightBrown, LightYellow}}}];
    
    customTabular[data,
      Dividers -> All,
      "Rotation" -> -90 Degree,
      FrameStyle -> {Darker@Red, Thick}
    ]
    

    enter image description here