Tables

From WeBWorK_wiki
Jump to navigation Jump to search
This article has been retained as a historical document. It is not up-to-date and the formatting may be lacking. Use the information herein with caution.

This problem has been replaced with many other problems:


Topic Name: Using Tables

This code snippet shows the essential PG code to display tables of data (or answer blanks, etc.). We give four different examples of how to display tables. Note that these are insertions, not a complete PG file. This code will have to be incorporated into the problem file on which you are working.

You may also be interested in GraphsInTables

  • Example 1: Tables made with niceTables.pl should conform to web accessibility standards and offer lots of freedom of decoration
  • Example 2: Standard tables embedded in the main text section
  • Example 3: Standard tables defined in the setup section and displayed in the main text section
  • Example 4: Union tables which offer more customization options

Problem Techniques Index

Example 1: A recommended method to put a table into a problem is to use niceTables.pl. The macros in niceTables.pl distinguish between data tables and layout tables. This and other features will make the table be web accessible, which is important for WeBWorK's status as an accessible online homework platform. Optionally, these macros can be used to decorate your tables in any number of ways. The examples that follow hopefully cover the most common features one might want for a table. A lot more is possible though than what is demonstrated here. See the documentation at the top of niceTables.pl.

Please note that niceTables.pl requires version 2.10 or later to work correctly.

PG problem snippet Explanation
loadMacros("niceTables.pl");

BEGIN_TEXT
\{
DataTable(
  [
    [['\(x\)', headerrow => 1],'\(x^2\)'],
    ['\(1\)',ans_rule(3)],
    ['\(2\)',ans_rule(3)]
  ], 
  caption => 'Values of \(x^2\)',
);
\}
END_TEXT

The DataTable macro takes the table's cells as a nested array reference. The outermost pair of brackets designates the entire table. The next level of brackets designates a row. In each row, there can simply be cell entries (like '\(1\)' or ans_rule(3)), or a cell entry can itself be an array reference that begins with the cell contents and is followed by some parameters. Here, the entry ['\(x\)', headerrow => 1] makes it so the entire row will consist of (column) headers. Those cells will be rendered onscreen using HTML table header elements for accessibility.

After the table's contents, options such as caption => '\(f(x) = x^2\)' can be set. For accessibility reasons, a data table should usually have some kind of caption.


BEGIN_TEXT
$PAR
\{
LayoutTable(
  [
    ['\(1^2={}\)'.ans_rule(3),'\(2^2={}\)'.ans_rule(3)],
    ['\(3^2={}\)'.ans_rule(3),'\(4^2={}\)'.ans_rule(3)],
  ], 
  align => 'r | r',
  center => 0,
);
\}
END_TEXT

The LayoutTable macro works in a similar way. In a layout table, the xy-position of a cell is not relevant, and the table structure is only being used for visual layout purposes. In a layout table, captions and headings should be irrelevant, and all directives involving these are ignored.

Here, we have also specified how we would like columns aligned. The align key should take a value like what LaTeX tabular environments can take. r stands for right-alignment, c stands for center-alignment, and l stands for left-alignment. The pipe character | is used to create a vertical bar between two columns.

The center option defaults to true, centering the whole table. It can be set to false as in this example.


BEGIN_TEXT
$PAR
\{
DataTable(
  [
    [['Name', headerrow => 1],'Biography'],
    [['James Kirk', i=>1],'James Tiberius Kirk was born 
       on March 22, 2233, in Riverside, Iowa.'],
    [['Jean-Luc Picard', m=>1],'Jean-Luc Picard was born 
       to Maurice and Yvette Picard in La Barre, France, 
       on July 13, 2305, and dreamed of joining 
       Starfleet.']
  ], 
  caption => 'Captains of the Enterprise',
  midrules => 1,
  align => 'p{1in} X',
);
\}
END_TEXT

Both DataTable and LayoutTable allow for a variety of formatting options. Formatting of on-screen and LaTeX hard copy versions are handled separately, and any standard formatting that could be done to a table using CSS onscreen or LaTeX in the hard copy is possible. For the more common formatting options, specifying the LaTeX hard copy formatting will automatically lead to a corresponding treatment of CSS for the onscreen version. Therefore it is generally recommended that you set whatever LaTeX hard copy parameters that you would like first, and then patch anything missing from the onscreen version with CSS commands. See the documentation at the top of niceTables.pl.

The midrules option can be set to true to give horizontal rules between rows (as well as above the first row and below the last).

Column alignment is set with the \align option as a string that one would use in a LaTeX tabular environment. In addition to the r, c, and l mentioned above, there are two types of columns for paragraph entries (cells that will have text that wraps). Using p{width} will create a column with a fixed-width. width should be a valid LaTeX width, such as 5cm, 8pc, etc. width will also be used in the onscreen CSS width specification, but if width is an invalid CSS width, then the browser's default will take over. The fifth column type is X. This column will be of an expandable width. All X columns will expand to fill the available width. More detail is in the comments at the top of niceTables.pl.

The i=>1 and m=>1 options can be used to make cell contents in italics or monospaced, respectively. Similarly b=>1 makes cell contents bold.

BEGIN_TEXT
$PAR
\{
DataTable(
  [
    [['x', headerrow => 1, midrule=>1, 
                        rowcolor => '{yellow}'],
      'x^2', 'x^3'],
    ['1','1',['1', tex => '\cellcolor{blue}']],
    ['2','4',[ans_rule(3), noencase=>1]]
  ], 
  caption => 'Some powers of some integers',
  encase => ['\(','\)'],
  align => '>{\columncolor{pink}}c c c'
);
\}
END_TEXT

Background colors can be set for individual cells, rows, or columns as in the example, and the colors will apply to both the onscreen and hard copy. Note that for a cell or a column, a full LaTeX command is specified, whereas for a row, only the argument of the LaTeX command is specified, complete with braces. In each of these cases, rather than using a named color as in the example, you could use the optional HTML argument and give a hexadecimal HTML color; for example \cellcolor[HMTL]{00FF00}. This has the advantage that the onscreen and hard copy colors will be identical, which is not guaranteed with named colors. Note that for accessibility reasons, you should never use color as the only means to communicate some piece of information.

In this example, a single midrule is used after the header row with the midrule option.

Also in this example, almost every cell should be in math mode. Rather than tediously type the \( and \) pairs, the encase option can be used. For cells that should not be encased, the noencase option can be used.


BEGIN_TEXT
$PAR
\{
DataTable(
  [
    ['hot', ['red', tex => '\color{red}'], 
     'orange', 'yellow'],
    ['cold', 'green', 'blue', 'purple']
  ], 
  caption => 'Hot and Cold Colors',
  align => '>{\color{gray}} l 
            >{\bfseries}    l 
            >{\itshape}     l 
            >{\ttfamily}    l',
  rowheaders => 1,
);
\}
END_TEXT

Fore color (for text and borders) may be set as in this example. Any cells in math mode may not render in color if the display mode is images. However MathJax math content should respect the coloring.

In this example, each row is given a row header with the rowheaders option.

Here we also demonstrate how to make an entire column bold, italicized, or in monospaced font.


BEGIN_TEXT
$PAR
\{
DataTable(
  [
    [['reptiles',headerrow=>1], 'mammals', 'birds'],
    [['lizard',rowcss => 'text-transform: uppercase; '],
      'bear', 'eagle'],
    [['turtle', texpre => '\scshape'], 'cow', 
     ['pelican', texencase => ['\underline{', '}']]],
    ['snake', 'lion', ['finch', 
            cellcss => 'text-transform: capitalize; ']],
  ], 
  caption => "This table's formatting is awful",
  tablecss=>'border:groove; border-collapse: separate; 
     border-radius: 10px; ',
  captioncss =>'font-family:cursive; ',
  columnscss => ['font-size:x-small; ',
     'font-size:medium; ', 'font-size:x-large; '],
  datacss => 'text-decoration: underline; ',
  headercss => 'background: linear-gradient(green, blue); ',
  allcellcss => 'font-family:fantasy; padding:10px; ',
);
\}
END_TEXT

Lastly, it is possible to edit the onscreen and hard copy versions separately. It's probably not a good idea to make the table be noticeably different onscreen than in the hard copy. But for some complicated decorating of a table, if the macro has not been designed to do it simultaneously in both places, these techniques would help apply something similar to each of the two output modes. In this example, various CSS and LaTeX altering options are used. Keep in mind that these examples only apply to one output form or the other.




Example 2: Prior to niceTables.pl, the simplest way of putting a table in the problem was just to embed it in the text of the problem using the begintable, row, and endtable commands, as shown below. It is also possible to use these to define variables that are used in the text; this is shown in the second example, below.

PG problem file Explanation
BEGIN_TEXT
Fill in the table of values for \(f(x) = x^2\).
$BCENTER
\{ begintable(4) \}
\{ row( "\(x = \)", "0", "1", "2" ) \}
\{ row( "\(f(x) = \)", ans_rule(5), ans_rule(5),
        ans_rule(5) ) \}
\{ endtable() \}
$ECENTER
END_TEXT

Main Text: The begintable, row, and endtable commands are all predefined in the PG language, so we just need to use them here. Because these are defined perl functions, we need to use the \{ \} constructs to execute them in the text section of the PG file.

Also note that, perhaps obviously, the begintable takes as its argument the number of columns in the table, and the row command takes a list of strings to put in the data elements in the row. In this example, we use the ans_rule function to put an answer blank in some table elements.

It is possible to use an array in a table row, and also to add more space around each entry in the table to make it look nicer. For example, we can add extra space manually using $SPACE, which must be inside double (not single) quotes. Obviously, if you're making computations using values in these arrays, add the extra $SPACE only after you're done making computations.

#  Setup
@x = (0..2); # shorthand for (0,1,2)
@f = (3..5);
foreach my $i (0..2) { 
  $x[$i] = "$SPACE $x[$i] $SPACE"; 
  $f[$i] = "$SPACE $f[$i] $SPACE"; 
}

#  Main text
BEGIN_TEXT
Fill in the table of values for \(f(x) = x^2\).
$BCENTER
\{ begintable(4) \}
\{ row( "$SPACE \(x = \) $SPACE", @x ) \}
\{ row( "$SPACE \(f(x) = \) $SPACE", @f ) \}
\{ endtable() \}
$ECENTER
END_TEXT



Example 3: We can also define as much of the table as we like in the problem set-up section of the problem file, as well, as suggested by the following example.


PG problem file Explanation
# we'll work with the function f(x) = x^2 + a
$a = random(2,5,1);

# the table data
$table_start = begintable(4);
$table_row1  = row( "\(x =\)", "0", "1", "2" );
$table_row2  = row( "\(f(x)\) =", ans_rule(5),
    ans_rule(5), ans_rule(5) );
$table_end   = endtable();

# these are the actual function values at the
#    points
@fvals = ();
foreach my $i ( 0, 1, 2 ) {
    push( @fvals, Compute("$i^2 + $a") );
}

Setup: In this example, we define the start of the table and the values in the table rows as variables that we can then use in the text section of the problem. We also define the function values at the points we're asking the student to compute.

It is also possible to join together these elements into a single value $table using the concatenation operation . between each element as follows.

$table = begintable(4) .
row( "\(x =\)", "0", "1", "2" ) .
row( "\(f(x)\) =",ans_rule(5),ans_rule(5),ans_rule(5) ) .
endtable();

BEGIN_TEXT
If \(f(x) = x^2 + $a\), fill in values of 
\(f(x)\) as indicated in the table below.
$BCENTER
$table_start
$table_row1
$table_row2
$table_end
$ECENTER
END_TEXT

Main Text: Then we put the table into the text section. If we had defined the table using only one element $table, we would insert it here in the same way as shown to the left.

foreach my $fv ( @fvals ) {
    ANS( $fv->cmp() );
}

Answer Evalution: And, given a list of answers, we can automate the insertion of answer checkers. Of course, with only three of them it would be faster to just put them in a list:

  ANS( $fvals[0]->cmp() );
  ANS( $fvals[1]->cmp() );
  ANS( $fvals[2]->cmp() );

instead of using the loop.


Example 4: We use the utilities provided by the unionTables.pl macro. This macro provides more customization than the previous two examples.


PG problem file Explanation
loadMacros(
"PGstandard.pl",
"unionTables.pl", # or "PGunion.pl",
);

BEGIN_TEXT
\{ 
BeginTable(border=>1, tex_border=>"1pt", spacing=>0, padding=>4).
AlignedRow(["\(x = \)","0","1","2"], align=>LEFT, separation=>0).
AlignedRow(["\(f(x)=\)","A","B","C"], separation=>0).
TableSpace(25,6).
AlignedRow(["\(g(x)=\)","E","F","G"], separation=>0).
EndTable()
\}
END_TEXT

In the initialization section of the PG file, be sure to load unionTables.pl (or PGunion.pl which will automatically load unionTables.pl).

Notice that the commands provided are case-sensitive (e.g., use BeginTable, not begintable). Because these are defined perl functions, we need to use the \{ \} constructs with curly braces to execute them in the text section of the PG file. Noe that periods are used at the end of each command (i.e., at the end of every line) except for the last command, since nothing will be joined to it.

For BeginTable(), the argument border=>n sets the border thickness to n pixels in HTML mode, while tex_border=>"1pt" sets the border thickness in TeX mode (for pdf hardcopies). Notice that the units pt must be included, where 1 point is 1/72 of an inch, and that the quotes around "1pt" are necessary. The options spacing and padding are like the HTML commands cellspacing and cellpadding. The default is center=>1 to center the table, but this could also be set to 0.

The AlignedRow() and Row() commands both take several arguments that allow further customization of how a table is displayed. The first argument is always a square bracketed list of entries in that row. Putting quotes around each entry is advised to prevent unexpected behavior (for example, try using E instead of "E"). For column separation, separation=>30 is the default, which is useful for a table of images, but less useful for a table of text. To insert a blank column on the left, use indent=>n for some number n (the default is n=0). The alignment of the initial column can be controlled by align => LEFT where the type is LEFT, RIGHT, or CENTER. The vertical alignment of a row is valign => MIDDLE where the type is TOP, MIDDLE, or BOTTOM.

The TableSpace(a,b) routine gives empty vertical space in the table of a pixels in HTML mode and b points in TeX mode. A relatively large space, say for separating images, would be TableSpace(25,6), while a small space to separate an image from its label in the next row down would be TableSpace(5,0).


Problem Techniques Index