# Dimensionality & hierarchies
URL: https://docs.valsight.ai/dimensionality-hierarchies/
Description: Use this category when you need to control a formula’s output shape: which dimensions and levels the result has, and at what granularity values exist.
Use this category when you need to **control a formula’s output shape**: which dimensions and levels the result has, and at what granularity values exist.

These functions let you aggregate to higher levels, remove detail, expand values to more detailed intersections, or distribute values across level values.

## Start here if…

* Your result is **too aggregated** and you lost more detail than expected
* Your result is **too granular** and contains more detail than expected
* Two nodes **won’t combine** cleanly because they have different dimensionality
* You want to **prepare a node for simulation** by creating the full dimensional space

## Not here if…

* You only need a numeric transformation such as scaling, rounding, or ratios → see [Math & numeric](/math-numeric/)
* You only need a subset of level values → see [Filtering & data shaping](/filtering-data-shaping/)

## Mental model

* **Roll up**: aggregate to higher levels
* **Drop**: remove levels from a dimension to simplify the shape
* **Expand**: add detail by creating combinations of level values
* **Distribute**: allocate values down to more detailed level values using a distribution key
* **Rebook**: move values between level values within the same level

## Common patterns

| Name                                 | What it does                                                                  | Formula                                           |
| ------------------------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------- |
| Aggregate to a higher level          | Use when you want values only at selected higher levels.                      | `ROLLUP('Node', "Dimension", "Level")`            |
| Match another node’s shape           | Use when you want one node aggregated to another node’s dimensionality.       | `ROLLUP_TO('Node', 'TargetShapeNode')`            |
| Remove unwanted granularity          | Use when a node carries detail you don’t want in further calculations.        | `DROPLEVEL('Node', "Level")`                      |
| Expand to more detail                | Use when you need a value available at a more detailed level.                 | `EXPAND('Node', "Level")`                         |
| Expand only to specific level values | Use when you want targeted expansion without creating the full cross product. | `EXPANDSINGLE('Node', "Level", ["A", "B"])`       |
| Create an empty simulation space     | Use when you want to initialize a node with the required dimensionality.      | `EXPAND(0, "Level1", "Level2")`                   |
| Allocate totals down to detail       | Use when you want allocations that preserve totals but add detail.            | `DISTRIBUTE('OriginalNode', 'DistributionNode')`  |
| Move values between level values     | Use when you need to reclassify values within the same level.                 | `REBOOK('Node', "Level", "OldValue", "NewValue")` |

## Functions in this category

| Function                       | Description                                                                                   |
| ------------------------------ | --------------------------------------------------------------------------------------------- |
| [EXPAND](/expand/)             | Expands a node or a specified value by adding the full cross product of the specified levels. |
| [EXPANDSINGLE](/expandsingle/) | Expands a node or a value to the specified level values.                                      |
| [DROPLEVEL](/droplevel/)       | Removes one or more levels (and any finer levels in the same dimension) from the node.        |
| [ROLLUP](/rollup/)             | Aggregates a node to only the specified levels.                                               |
| [ROLLUP\_TO](/rollup-to/)      | Aggregates the first node to match the level dimensionality of the second node.               |
| [DISTRIBUTE](/distribute/)     | Distributes values of one node across levels based on another node’s value distribution.      |
| [REDISTRIBUTE](/redistribute/) | Redistributes a value within specified clusters, weighted by a distribution measure.          |
| [REBOOK](/rebook/)             | Rebooks numeric values from one level value to another within the same level.                 |

## Choosing between similar functions

**ROLLUP vs DROPLEVEL**

* Use `ROLLUP` when you want an explicit aggregation target
* Use `DROPLEVEL` when you want to remove specific granularity from a dimension

**EXPAND vs EXPANDSINGLE**

* Use `EXPAND` when you want the full cross product for a level
* Use `EXPANDSINGLE` when you only want specific level values

**ROLLUP vs ROLLUP\_TO**

* Use `ROLLUP` when you know the target levels
* Use `ROLLUP_TO` when another node already defines the target shape

**DISTRIBUTE vs REDISTRIBUTE**

* Use `DISTRIBUTE` to allocate values down using a distribution key
* Use `REDISTRIBUTE` when allocation should happen only within defined clusters

**REBOOK vs DISTRIBUTE**

* Use `REBOOK` when you want to move values from one level value to another
* Use `DISTRIBUTE` or `REDISTRIBUTE` when you want to split totals across multiple level values using weights

## Pitfalls & troubleshooting

* **Result is too aggregated:** check whether `+` or `-` aligned to shared dimensions; make the intended shape explicit with `ROLLUP` or `ROLLUP_TO`
* **Result is too granular or too large:** check whether `*` or `/` expanded across combined dimensions or whether an `EXPAND` added more detail than intended
* **Result is empty after reshaping:** confirm referenced levels/level values exist and labels match exactly (spelling/case)
* **Unexpected allocation results:** verify the distribution key node has values at the target detail and that totals behave as expected after distribution
* **Element-wise adjustment needed:** use `ADDEACH` rather than relying on `+ constant` behavior

## Related documentation

* [Filtering & data shaping](/filtering-data-shaping/): subset selection and fill or pick helpers
* [Operators](/operators/): alignment behavior and comparisons used inside formulas
* [Troubleshooting guide](/troubleshooting-guide/): wrong shape and missing values
* [Function catalog](/function-catalog/): full signatures, parameters, and examples
