In This Vignette

  • Results of Pivot Calculations
  • Example Pivot Table
  • Results as Plain Text
  • Results as HTML
  • Results as Latex
  • Results in Excel
  • Results as FlexTable
  • Results in Word
  • Results in PowerPoint
  • Results as an R Matrix
  • Results as an R Data Frame
  • Results as a basictabler Table
  • Further Reading

Results of Pivot Calculations

A pivottabler pivot table object has a fairly complex internal structure - containing two trees of data groups (the row groups and the column groups) plus a set of cells linked to the data groups.

The pivottabler package supports outputting a pivot table in a number of different forms:

  • A htmlwidget for R-Studio - using pt$renderPivot() to render the pivot table into the “Viewer” tab in R-Studio,
  • A htmlwidget for Shiny applications - using pivottabler(pt) to render the pivot table into the Shiny app,
  • As HTML - using either:
    • pt$getHtml() to retrieve a character variable containing HTML, or
    • pt$saveHtml() to save the HTML to a file.
  • As Latex - using pt$getLatex() to retrieve a character variable containing Latex.
  • As plain text - using pt to output to the console or pt$asCharacter to retrieve as a character value.
  • Into an Excel Worksheet.

Sometimes it is desirable to retrieve the pivot table results as a more standard data type that is easier to work with in R code. A pivot table can be converted to either a matrix or a data frame. Neither data type is a perfect representation of a pivot table - which option is better will depend upon your use case.

Example Pivot Table

The following pivot table is used as the basis of the examples in the rest of this vignette:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$renderPivot()

Results as Plain Text

A pivot table is outputted to the console as plain text simply by using pt:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
pt
                     DMU    EMU    HST  Total  
Arriva Trains Wales   3909               3909  
CrossCountry         22196         732  22928  
London Midland       11229  37050       48279  
Virgin Trains         2137   6457        8594  
Total                39471  43507  732  83710  

Alternatively, the plain text representation of the pivot table can be retrieved as a character value using pt$asCharacter.

pt and pt$asString show the current state of the pivot table. If the pivot table has not been evaluated (either by using pt$evaluatePivot() or pt$renderPivot()) then pt and pt$asCharacter will return the headings only:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt
                     DMU  EMU  HST  Total  
Arriva Trains Wales  
CrossCountry         
London Midland       
Virgin Trains        
Total                

Results as HTML

Rendering a htmlwidget

A pivot table is outputted as a htmlwidget simply by calling pt$renderPivot(). There are numerous examples throughout these vignettes, including the example directly above.

For outputting as a htmlwidget in a Shiny application, use pivottabler(pt).

Retrieving HTML

To retrieve the HTML of a pivot table, use pt$getHtml(). This returns a list of html tag objects built using the htmltools package. This object can be converted to a simple character variable using as.character() or as illustrated below. The CSS declarations for a pivot table can be retrieved using pt$getCss() - also illustrated below.

library(pivottabler)
library(htmltools)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
cat(paste(pt$getHtml(), sep="", collapse="\n"))
<table class="Table">
  <tr>
    <th class="RowHeader">&nbsp;</th>
    <th class="ColumnHeader">DMU</th>
    <th class="ColumnHeader">EMU</th>
    <th class="ColumnHeader">HST</th>
    <th class="ColumnHeader">Total</th>
  </tr>
  <tr>
    <th class="RowHeader">Arriva Trains Wales</th>
    <td class="Cell">3909</td>
    <td class="Cell"></td>
    <td class="Cell"></td>
    <td class="Total">3909</td>
  </tr>
  <tr>
    <th class="RowHeader">CrossCountry</th>
    <td class="Cell">22196</td>
    <td class="Cell"></td>
    <td class="Cell">732</td>
    <td class="Total">22928</td>
  </tr>
  <tr>
    <th class="RowHeader">London Midland</th>
    <td class="Cell">11229</td>
    <td class="Cell">37050</td>
    <td class="Cell"></td>
    <td class="Total">48279</td>
  </tr>
  <tr>
    <th class="RowHeader">Virgin Trains</th>
    <td class="Cell">2137</td>
    <td class="Cell">6457</td>
    <td class="Cell"></td>
    <td class="Total">8594</td>
  </tr>
  <tr>
    <th class="RowHeader">Total</th>
    <td class="Total">39471</td>
    <td class="Total">43507</td>
    <td class="Total">732</td>
    <td class="Total">83710</td>
  </tr>
</table>
cat(pt$getCss())
.Table {display: table; border-collapse: collapse; }
.ColumnHeader {font-family: Arial; font-size: 0.75em; border: 1px solid lightgray; vertical-align: middle; font-weight: bold; background-color: #F2F2F2; padding: 2px; text-align: center; }
.RowHeader {font-family: Arial; font-size: 0.75em; border: 1px solid lightgray; vertical-align: middle; font-weight: bold; background-color: #F2F2F2; padding: 2px 8px 2px 2px; text-align: left; }
.Cell {font-family: Arial; font-size: 0.75em; padding: 2px 2px 2px 8px; border: 1px solid lightgray; vertical-align: middle; text-align: right; }
.OutlineColumnHeader {font-family: Arial; font-size: 0.75em; border: 1px solid lightgray; vertical-align: middle; font-weight: bold; background-color: #F2F2F2; padding: 2px; text-align: center; }
.OutlineRowHeader {font-family: Arial; font-size: 0.75em; border: 1px solid lightgray; vertical-align: middle; font-weight: bold; background-color: #F2F2F2; padding: 2px 8px 2px 2px; text-align: left; }
.OutlineCell {font-family: Arial; font-size: 0.75em; padding: 2px 2px 2px 8px; border: 1px solid lightgray; vertical-align: middle; text-align: right; background-color: #F8F8F8; font-weight: bold; }
.Total {font-family: Arial; font-size: 0.75em; padding: 2px 2px 2px 8px; border: 1px solid lightgray; vertical-align: middle; text-align: right; }

Results as Latex

Please see the Latex Output vignette.

Results in Excel

Please see the Excel Export vignette.

Results as FlexTable

Converting a pivot table to a table from the flextabler package is possible:

# construct the table
library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()

# convert to a basictabler table
library(basictabler)
tbl <- pt$asBasicTable()

# convert to flextable
library(flextable)
ft <- tbl$asFlexTable()
ft

DMU

EMU

HST

Total

Arriva Trains Wales

3909

3909

CrossCountry

22196

732

22928

London Midland

11229

37050

48279

Virgin Trains

2137

6457

8594

Total

39471

43507

732

83710

Results in Word

Converting a pivot table to a Word document is possible using the flextabler package:

# construct the table
library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()

# convert to a basictabler table
library(basictabler)
tbl <- pt$asBasicTable()

# convert to flextable
library(flextable)
ft <- tbl$asFlexTable()

# save word document
library(officer)
docx <- read_docx()
docx <- body_add_par(docx, "Example Table")
docx <- body_add_flextable(docx, value = ft)
print(docx, target = "example_table_word.docx")

Results in PowerPoint

Converting a pivot table to a PowerPoint document is possible using the flextabler package:

# construct the table
library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()

# convert to a basictabler table
library(basictabler)
tbl <- pt$asBasicTable()

# convert to flextable
library(flextable)
ft <- tbl$asFlexTable()

# save PowerPoint document
library(officer)
ppt <- read_pptx()
ppt <- add_slide(ppt, layout = "Title and Content", master = "Office Theme")
ppt <- ph_with(ppt, value = ft, location = ph_location_left()) 
print(ppt, target = "example_table_powerpoint.pptx")

Results as an R Matrix

As a Data Matrix

Converting a pivot table to a matrix is possible. The row/column headers become the row/column names in the matrix:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
pt$asDataMatrix()
                      DMU   EMU HST Total
Arriva Trains Wales  3909    NA  NA  3909
CrossCountry        22196    NA 732 22928
London Midland      11229 37050  NA 48279
Virgin Trains        2137  6457  NA  8594
Total               39471 43507 732 83710

If only the cell values are required, the headings can be removed from the matrix by setting the includeHeaders parameter to FALSE.

By default, asDataMatrix() populates the matrix with the raw cell values. Setting the rawValue parameter to FALSE specifies that the matrix should contain the formatted character values instead of the raw values.

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
pt$asDataMatrix(rawValue=FALSE)
                    DMU     EMU     HST   Total  
Arriva Trains Wales "3909"  NA      NA    "3909" 
CrossCountry        "22196" NA      "732" "22928"
London Midland      "11229" "37050" NA    "48279"
Virgin Trains       "2137"  "6457"  NA    "8594" 
Total               "39471" "43507" "732" "83710"

When there are multiple levels of headers, headers are concatenated. A separator can be specified:

library(dplyr)
library(pivottabler)
data <- filter(bhmtrains, (Status=="A")|(Status=="C"))
pt <- PivotTable$new()
pt$addData(data)
pt$addColumnDataGroups("PowerType", addTotal=FALSE)
pt$addColumnDataGroups("Status", addTotal=FALSE)
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$renderPivot()
pt$asDataMatrix(separator="|")
                    DMU|A DMU|C EMU|A EMU|C HST|A HST|C
Arriva Trains Wales  3833    74    NA    NA    NA    NA
CrossCountry        21621   548    NA    NA   709    23
London Midland      11054   168 35930  1082    NA    NA
Virgin Trains        2028   107  6331   119    NA    NA
Total               38536   897 42261  1201   709    23

As a character matrix

It is also possible to convert a pivot table to a character matrix, where the row/column names are within the body of the matrix:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
pt$asMatrix()
     [,1]                  [,2]    [,3]    [,4]  [,5]   
[1,] ""                    "DMU"   "EMU"   "HST" "Total"
[2,] "Arriva Trains Wales" "3909"  ""      ""    "3909" 
[3,] "CrossCountry"        "22196" ""      "732" "22928"
[4,] "London Midland"      "11229" "37050" ""    "48279"
[5,] "Virgin Trains"       "2137"  "6457"  ""    "8594" 
[6,] "Total"               "39471" "43507" "732" "83710"

If only the cell values are required, the headings can be removed from the matrix by setting the includeHeaders parameter to FALSE.

When there are multiple levels of headers, by default the column headers are not repeated:

library(dplyr)
library(pivottabler)
data <- filter(bhmtrains, (Status=="A")|(Status=="C"))
pt <- PivotTable$new()
pt$addData(data)
pt$addColumnDataGroups("PowerType", addTotal=FALSE)
pt$addColumnDataGroups("Status", addTotal=FALSE)
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$renderPivot()
pt$asMatrix()
     [,1]                  [,2]    [,3]  [,4]    [,5]   [,6]  [,7]
[1,] ""                    "DMU"   ""    "EMU"   ""     "HST" ""  
[2,] ""                    "A"     "C"   "A"     "C"    "A"   "C" 
[3,] "Arriva Trains Wales" "3833"  "74"  ""      ""     ""    ""  
[4,] "CrossCountry"        "21621" "548" ""      ""     "709" "23"
[5,] "London Midland"      "11054" "168" "35930" "1082" ""    ""  
[6,] "Virgin Trains"       "2028"  "107" "6331"  "119"  ""    ""  
[7,] "Total"               "38536" "897" "42261" "1201" "709" "23"

However, the repeatHeaders parameter can be used to specify repeating headings:

pt$asMatrix(repeatHeaders=TRUE)
     [,1]                  [,2]    [,3]  [,4]    [,5]   [,6]  [,7] 
[1,] ""                    "DMU"   "DMU" "EMU"   "EMU"  "HST" "HST"
[2,] ""                    "A"     "C"   "A"     "C"    "A"   "C"  
[3,] "Arriva Trains Wales" "3833"  "74"  ""      ""     ""    ""   
[4,] "CrossCountry"        "21621" "548" ""      ""     "709" "23" 
[5,] "London Midland"      "11054" "168" "35930" "1082" ""    ""   
[6,] "Virgin Trains"       "2028"  "107" "6331"  "119"  ""    ""   
[7,] "Total"               "38536" "897" "42261" "1201" "709" "23" 

Results as an R Data Frame

Two different functions can be used to convert a pivot table to a data frame. The asDataFrame() function returns a data frame with a roughly similar layout to the pivot table, e.g. a pivot table with a body consisting of 10 rows and 2 columns will result in a data frame also containing 10 rows and 2 columns. The asTidyDataFrame() function returns a data frame consisting of one row for every cell in the body of the pivot table, e.g. a pivot table with a body consisting of 10 rows and 2 columns will result in a data frame containing 20 rows.

Examples of both functions are given below.

The asDataFrame() function

The example pivot table converts as follows:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
df <- pt$asDataFrame()
df
                      DMU   EMU HST Total
Arriva Trains Wales  3909    NA  NA  3909
CrossCountry        22196    NA 732 22928
London Midland      11229 37050  NA 48279
Virgin Trains        2137  6457  NA  8594
Total               39471 43507 732 83710
str(df)
'data.frame':   5 obs. of  4 variables:
 $ DMU  : int  3909 22196 11229 2137 39471
 $ EMU  : int  NA NA 37050 6457 43507
 $ HST  : int  NA 732 NA NA 732
 $ Total: int  3909 22928 48279 8594 83710

Data frames can have at most one name for each row and column. Therefore, when there are multiple levels of headers in the pivot table, the captions are concatenated into a single value for each row and column:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("TrainCategory")
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
pt$asDataFrame()
                    Express Passenger DMU Express Passenger EMU
Arriva Trains Wales                  3079                    NA
CrossCountry                        22133                    NA
London Midland                       5638                  8849
Virgin Trains                        2137                  6457
Total                               32987                 15306
                    Express Passenger HST Express Passenger Total
Arriva Trains Wales                    NA                    3079
CrossCountry                          732                   22865
London Midland                         NA                   14487
Virgin Trains                          NA                    8594
Total                                 732                   49025
                    Ordinary Passenger DMU Ordinary Passenger EMU
Arriva Trains Wales                    830                     NA
CrossCountry                            63                     NA
London Midland                        5591                  28201
Virgin Trains                           NA                     NA
Total                                 6484                  28201
                    Ordinary Passenger Total Total 
Arriva Trains Wales                      830   3909
CrossCountry                              63  22928
London Midland                         33792  48279
Virgin Trains                             NA   8594
Total                                  34685  83710

The space character is the default character used to combine headers as seen above. This can easily be changed, e.g. to a pipe character:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("TrainCategory")
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
pt$asDataFrame(separator="|")
                    Express Passenger|DMU Express Passenger|EMU
Arriva Trains Wales                  3079                    NA
CrossCountry                        22133                    NA
London Midland                       5638                  8849
Virgin Trains                        2137                  6457
Total                               32987                 15306
                    Express Passenger|HST Express Passenger|Total
Arriva Trains Wales                    NA                    3079
CrossCountry                          732                   22865
London Midland                         NA                   14487
Virgin Trains                          NA                    8594
Total                                 732                   49025
                    Ordinary Passenger|DMU Ordinary Passenger|EMU
Arriva Trains Wales                    830                     NA
CrossCountry                            63                     NA
London Midland                        5591                  28201
Virgin Trains                           NA                     NA
Total                                 6484                  28201
                    Ordinary Passenger|Total Total|
Arriva Trains Wales                      830   3909
CrossCountry                              63  22928
London Midland                         33792  48279
Virgin Trains                             NA   8594
Total                                  34685  83710

In addition, the row group headings can be exported as separate columns:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("TrainCategory")
pt$addRowDataGroups("TOC")
pt$addRowDataGroups("PowerType")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
pt$asDataFrame(rowGroupsAsColumns=TRUE)
                                          TOC PowerType Express Passenger
Arriva Trains Wales DMU   Arriva Trains Wales       DMU              3079
Arriva Trains Wales Total Arriva Trains Wales     Total              3079
CrossCountry DMU                 CrossCountry       DMU             22133
CrossCountry HST                 CrossCountry       HST               732
CrossCountry Total               CrossCountry     Total             22865
London Midland DMU             London Midland       DMU              5638
London Midland EMU             London Midland       EMU              8849
London Midland Total           London Midland     Total             14487
Virgin Trains DMU               Virgin Trains       DMU              2137
Virgin Trains EMU               Virgin Trains       EMU              6457
Virgin Trains Total             Virgin Trains     Total              8594
Total                                   Total                       49025
                          Ordinary Passenger Total
Arriva Trains Wales DMU                  830  3909
Arriva Trains Wales Total                830  3909
CrossCountry DMU                          63 22196
CrossCountry HST                          NA   732
CrossCountry Total                        63 22928
London Midland DMU                      5591 11229
London Midland EMU                     28201 37050
London Midland Total                   33792 48279
Virgin Trains DMU                         NA  2137
Virgin Trains EMU                         NA  6457
Virgin Trains Total                       NA  8594
Total                                  34685 83710

The asTidyDataFrame() function

The example pivot table converts as follows:

library(pivottabler)
pt <- PivotTable$new()
pt$addData(bhmtrains)
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()
pt$asDataFrame()
                      DMU   EMU HST Total
Arriva Trains Wales  3909    NA  NA  3909
CrossCountry        22196    NA 732 22928
London Midland      11229 37050  NA 48279
Virgin Trains        2137  6457  NA  8594
Total               39471 43507 732 83710
df <- pt$asTidyDataFrame()
str(df)
'data.frame':   20 obs. of  11 variables:
 $ rowNumber           : int  1 1 1 1 2 2 2 2 3 3 ...
 $ columnNumber        : int  1 2 3 4 1 2 3 4 1 2 ...
 $ isTotal             : logi  FALSE FALSE FALSE TRUE FALSE FALSE ...
 $ RowLevel01          : chr  "Arriva Trains Wales" "Arriva Trains Wales" "Arriva Trains Wales" "Arriva Trains Wales" ...
 $ ColumnLevel01       : chr  "DMU" "EMU" "HST" "Total" ...
 $ TOC                 : chr  "Arriva Trains Wales" "Arriva Trains Wales" "Arriva Trains Wales" "Arriva Trains Wales" ...
 $ PowerType           : chr  "DMU" "EMU" "HST" "NA" ...
 $ calculationName     : chr  "TotalTrains" "TotalTrains" "TotalTrains" "TotalTrains" ...
 $ calculationGroupName: chr  "default" "default" "default" "default" ...
 $ rawValue            : int  3909 NA NA 3909 22196 NA 732 22928 11229 37050 ...
 $ formattedValue      : chr  "3909" NA NA "3909" ...
head(df)
  rowNumber columnNumber isTotal          RowLevel01 ColumnLevel01
1         1            1   FALSE Arriva Trains Wales           DMU
2         1            2   FALSE Arriva Trains Wales           EMU
3         1            3   FALSE Arriva Trains Wales           HST
4         1            4    TRUE Arriva Trains Wales         Total
5         2            1   FALSE        CrossCountry           DMU
6         2            2   FALSE        CrossCountry           EMU
                  TOC PowerType calculationName calculationGroupName rawValue
1 Arriva Trains Wales       DMU     TotalTrains              default     3909
2 Arriva Trains Wales       EMU     TotalTrains              default       NA
3 Arriva Trains Wales       HST     TotalTrains              default       NA
4 Arriva Trains Wales        NA     TotalTrains              default     3909
5        CrossCountry       DMU     TotalTrains              default    22196
6        CrossCountry       EMU     TotalTrains              default       NA
  formattedValue
1           3909
2           <NA>
3           <NA>
4           3909
5          22196
6           <NA>

By default the generated pivot table contains columns for both the captions of the data groups and the variables/values that the data groups represent. Each of these sets of columns can be removed from the data frame by setting includeGroupCaptions=FALSE or includeGroupValues=FALSE respectively.

Where a data group represents multiple values, those values are concatenated and returned in a single column in the data frame. Again, the separator between the values can be changed, e.g. by specifying separator="|".

Results as a basictabler Table

The asBasicTable() function allows a pivot table to be converted to a basic table - from the basictabler package.

The basictabler package allows free-form tables to be constructed, in contrast to pivottabler which creates pivot tables with relatively fixed structures. pivottabler contains calculation logic - to calculate the values of cells within the pivot table. basictabler contains no calculation logic - cell values must be provided either from a data frame, row-by-row, column-by-column or cell-by-cell.

Converting a pivot table to a basic table allows the structure of pivot tables to be altered after they have been created, e.g.

library(pivottabler)
library(dplyr)
library(lubridate)
trains <- mutate(bhmtrains, 
                 GbttDate=if_else(is.na(GbttArrival), GbttDeparture, GbttArrival),
                 GbttMonth=make_date(year=year(GbttDate), month=month(GbttDate), day=1))

pt <- PivotTable$new()
pt$addData(trains)
pt$addColumnDataGroups("GbttMonth", dataFormat=list(format="%B %Y"))
pt$addColumnDataGroups("PowerType")
pt$addRowDataGroups("TOC")
pt$defineCalculation(calculationName="TotalTrains", summariseExpression="n()")
pt$evaluatePivot()

# convert the pivot table to a basic table, insert a new row, merge cells and highlight
bt <- pt$asBasicTable()
bt$cells$insertRow(5)
bt$cells$setCell(5, 2, rawValue="The values below are significantly higher than expected.", 
                 styleDeclarations=list("text-align"="left", "background-color"="yellow",
                                        "font-weight"="bold", "font-style"="italic"))
bt$mergeCells(rFrom=5, cFrom=2, rSpan=1, cSpan=13)
bt$setStyling(rFrom=6, cFrom=2, rTo=6, cTo=14, 
              declarations=list("text-align"="left", "background-color"="yellow"))
bt$renderTable()