Thanks, Mark!
Here is the code for the function RecordSummary that can be used together with Grid to make summary tables:
Clear[DataColumnsSummary]
Options[DataColumnsSummary] = {"MaxTallies" -> 7, "NumberedColumns" -> True};
DataColumnsSummary[dataColumns_, opts : OptionsPattern[]] :=
DataColumnsSummary[dataColumns,
Table["column " <> ToString[i], {i, 1, Length[dataColumns]}], opts];
DataColumnsSummary[dataColumns_, columnNamesArg_, opts : OptionsPattern[]] :=
Block[{columnTypes, columnNames = columnNamesArg,
maxTallies = OptionValue[DataColumnsSummary, "MaxTallies"],
numberedColumnsQ =
TrueQ[OptionValue[DataColumnsSummary, "NumberedColumns"]]},
If[numberedColumnsQ,
columnNames =
MapIndexed[ToString[#2[[1]]] <> " " <> #1 &, columnNames]
];
columnTypes =
Map[If[NumberQ[#], Number, Symbol] &, dataColumns[[All, 1]]];
MapThread[
Column[{
Style[#1, Blue, FontFamily -> "Times"],
If[TrueQ[#2 === Number],
Grid[NumericVectorSummary[#3], Alignment -> Left],
Grid[CategoricalVectorSummary[#3, maxTallies],
Alignment -> Left]
]}] &, {columnNames, columnTypes, dataColumns}, 1]
] /; Length[dataColumns] == Length[columnNamesArg];
Clear[RecordsSummary];
RecordsSummary[dataRecords_, opts : OptionsPattern[]] :=
DataColumnsSummary[Transpose[dataRecords], opts];
RecordsSummary[dataRecords_, columnNames_, opts : OptionsPattern[]] :=
DataColumnsSummary[Transpose[dataRecords], columnNames, opts];