Theoretically, Dataset supports any number of columns.
The behavior you are seeing is actually because the type deduction that Dataset is doing behind the scenes isn't perfect (and indeed in some sense cannot be perfect). Your synthetic example is such that your second list of associations is "most consistent" with a particular type that doesn't typeset as a table.
You can see what type Dataset deduced in a given case by using Dataset`GetType
. First get TypeSystem
onto your context path, so that the types aren't fully qualified and are easier to read:
Needs["TypeSystem`"];
Then use GetType
:
In[2]:= Dataset`GetType @ Dataset @ Table[Association[ToString[#] -> # & /@ Range[4]], {2}]
Out[2]= Vector[Struct[{"1", "2", "3", "4"},
{Atom[Integer], Atom[Integer], Atom[Integer], Atom[Integer]}], 2]
Notice that the type of your data has been deduced to be a Vector
(homogenous list) of Structs
s (heterogenous associations), or in other words a row-oriented table.
But now do:
In[3]:= Dataset`GetType @ Dataset @ Table[Association[ToString[#] -> # & /@ Range[5]], {2}]
Out[3]= Vector[Assoc[Atom[String], Atom[Integer], 5], 2]
Here, your data has been deduced as a Vector
of Assoc
s (homogenous associations). Assocs
are a type that doesn't care what keys are present, just that they all have the same type, and also that the values have the same type.
That happened because according to the internal heuristics, an Assoc
is considered to be a more parsimonious type as soon as we cross the threshold of 4 fields. But this would not be true if we looked at an association whose values were different types, instead of all being integers:
In[2]:= DeduceType @ Table[<|"A" -> 1, "B" -> 2, "C" -> 3, "D" -> 4, "E" -> "bar"|>, {5}]
Out[2]= Vector[Struct[{"A", "B", "C", "D", "E"},
{Atom[Integer], Atom[Integer], Atom[Integer], Atom[Integer], Atom[String]}], 5]
The only consistent type here is a Vector
of Structs
(notice I'm using DeduceType
directly, which is what Dataset uses upon construction). And indeed, this more complex Dataset typesets as a table, owing to the inner Struct
type:

Although it isn't documented and is therefore of course subject to change, you can force a specific type to be used by supplying a second argument to Dataset:
Dataset[
Table[Association[ToString[#] -> # & /@ Range[5]], {5}],
Vector[Struct[{"1", "2", "3", "4", "5"},
{Atom[Integer], Atom[Integer], Atom[Integer], Atom[Integer], Atom[Integer]}]]]
This will typeset as a table, as you desire:

viewDataset
for tabular datasets here. $\endgroup$