<a id="sphx-glr-auto-examples-clustering-plot-1-hrp-cvar-py"></a>

<a id="hierarchical-risk-parity-cvar"></a>

# Hierarchical Risk Parity - CVaR

This tutorial introduces the [`HierarchicalRiskParity`](https://skfolio.org/generated/skfolio.optimization.HierarchicalRiskParity.html.md#skfolio.optimization.HierarchicalRiskParity)
optimization.

Hierarchical Risk Parity (HRP) is a portfolio optimization method developed by Marcos
Lopez de Prado.

This algorithm uses a distance matrix to compute hierarchical clusters using the
Hierarchical Tree Clustering algorithm. It then employs seriation to rearrange the
assets in the dendrogram, minimizing the distance between leaves.

The final step is the recursive bisection where each cluster is split between two
sub-clusters by starting with the topmost cluster and traversing in a top-down
manner. For each sub-cluster, we compute the total cluster risk of an inverse-risk
allocation. A weighting factor is then computed from these two sub-cluster risks,
which is used to update the cluster weight.

#### NOTE
The original paper uses the variance as the risk measure and the single-linkage
method for the Hierarchical Tree Clustering algorithm. Here we generalize it to
multiple risk measures and linkage methods.
The default linkage method is set to the Ward
variance minimization algorithm, which is more stable and has better properties
than the single-linkage method.

In this example, we will use the CVaR risk measure.

<a id="data"></a>

## Data

We load the S&P 500 [dataset](https://skfolio.org/user_guide/datasets.html.md#datasets) composed of the daily prices of 20
assets from the SPX Index composition and the Factors dataset composed of the daily
prices of 5 ETFs representing common factors:

```Python
from plotly.io import show
from sklearn.model_selection import train_test_split

from skfolio import Population, RiskMeasure
from skfolio.cluster import HierarchicalClustering, LinkageMethod
from skfolio.datasets import load_factors_dataset, load_sp500_dataset
from skfolio.distance import KendallDistance
from skfolio.optimization import EqualWeighted, HierarchicalRiskParity
from skfolio.preprocessing import prices_to_returns
from skfolio.prior import TimeSeriesFactorModel

prices = load_sp500_dataset()
factor_prices = load_factors_dataset()

prices = prices["2014":]
factor_prices = factor_prices["2014":]

X, factors = prices_to_returns(prices, factor_prices)
X_train, X_test, factors_train, factors_test = train_test_split(
    X, factors, test_size=0.33, shuffle=False
)
```

<a id="model"></a>

## Model

We create the CVaR Hierarchical Risk Parity model and then fit it on the training set:

```Python
model1 = HierarchicalRiskParity(
    risk_measure=RiskMeasure.CVAR, portfolio_params=dict(name="HRP-CVaR-Ward-Pearson")
)
model1.fit(X_train)
model1.weights_
```

```none
array([0.05033705, 0.02773558, 0.05289115, 0.03632272, 0.059202  ,
       0.02483767, 0.03790179, 0.07464383, 0.03497807, 0.08622477,
       0.06308422, 0.04094166, 0.03144452, 0.08277551, 0.04421773,
       0.04807705, 0.02596219, 0.07596741, 0.0393462 , 0.06310889])
```

<a id="risk-contribution"></a>

## Risk Contribution

Let’s analyze the risk contribution of the model on the training set:

```Python
ptf1 = model1.predict(X_train)
ptf1.plot_contribution(measure=RiskMeasure.CVAR)
```

<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>[plotly figure stripped from llms output]
<br />
<br />

<a id="dendrogram"></a>

## Dendrogram

To analyze the clusters structure, we plot the dendrogram.
The blue lines represent distinct clusters composed of a single asset.
The remaining colors represent clusters of more than one asset:

```Python
model1.hierarchical_clustering_estimator_.plot_dendrogram(heatmap=False)
```

<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>[plotly figure stripped from llms output]
<br />
<br />

The horizontal axis represents the assets. The links between clusters are represented
as upside-down U-shaped lines. The height of the U indicates the distance between the
clusters. For example, the link representing the cluster containing assets HD and WMT
has a distance of 0.5 (called cophenetic distance).

When `heatmap` is set to True, the heatmap of the reordered distance matrix is
displayed below the dendrogram and clusters are outlined with yellow squares:

```Python
fig = model1.hierarchical_clustering_estimator_.plot_dendrogram()
show(fig)
```

[plotly figure stripped from llms output]<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>

<a id="linkage-methods"></a>

## Linkage Methods

The clustering can be greatly affected by the choice of the linkage method.
The original HRP is based on the single-linkage (equivalent to the minimum spanning
tree), which suffers from the chaining effect.
In the [`HierarchicalRiskParity`](https://skfolio.org/generated/skfolio.optimization.HierarchicalRiskParity.html.md#skfolio.optimization.HierarchicalRiskParity) estimator, the default
linkage method is set to the Ward variance minimization algorithm, which is more
stable and has better properties than the single-linkage method.

However, since the HRP optimization doesn’t utilize the full cluster structure but
only their orders, the allocation remains relatively stable regardless of the chosen
linkage method.

```Python
# To show this effect, let's create a second model with the single-linkage method:
model2 = HierarchicalRiskParity(
    risk_measure=RiskMeasure.CVAR,
    hierarchical_clustering_estimator=HierarchicalClustering(
        linkage_method=LinkageMethod.SINGLE,
    ),
    portfolio_params=dict(name="HRP-CVaR-Single-Pearson"),
)
model2.fit(X_train)

model2.hierarchical_clustering_estimator_.plot_dendrogram(heatmap=True)
```

<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>[plotly figure stripped from llms output]
<br />
<br />

We can see that the clustering has been greatly affected by the change of the linkage
method. However, you will see below that the weights remain relatively stable for the
reason explained earlier.

<a id="distance-estimator"></a>

## Distance Estimator

The choice of distance metric also has an important effect on the clustering.
The default is to use the distance from the pearson correlation matrix.
This can be changed using the [distance estimators](https://skfolio.org/user_guide/distance.html.md#distance).

For example, let’s create a third model with a distance computed from the absolute
value of the Kendal correlation matrix:

```Python
model3 = HierarchicalRiskParity(
    risk_measure=RiskMeasure.CVAR,
    distance_estimator=KendallDistance(absolute=True),
    portfolio_params=dict(name="HRP-CVaR-Ward-Kendal"),
)
model3.fit(X_train)

model3.hierarchical_clustering_estimator_.plot_dendrogram(heatmap=True)
```

<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>[plotly figure stripped from llms output]
<br />
<br />

<a id="prior-estimator"></a>

## Prior Estimator

Finally, HRP like the other portfolio optimization, uses a
[prior estimator](https://skfolio.org/user_guide/prior.html.md#prior) that fits a [`ReturnDistribution`](https://skfolio.org/generated/skfolio.prior.ReturnDistribution.html.md#skfolio.prior.ReturnDistribution)
containing the distribution estimate of asset returns.
The default is the [`EmpiricalPrior`](https://skfolio.org/generated/skfolio.prior.EmpiricalPrior.html.md#skfolio.prior.EmpiricalPrior) estimator.

Let’s create new model with the [`TimeSeriesFactorModel`](https://skfolio.org/generated/skfolio.prior.TimeSeriesFactorModel.html.md#skfolio.prior.TimeSeriesFactorModel) estimator:

```Python
model4 = HierarchicalRiskParity(
    risk_measure=RiskMeasure.CVAR,
    prior_estimator=TimeSeriesFactorModel(),
    portfolio_params=dict(name="HRP-CVaR-Factor-Model"),
)
model4.fit(X_train, factors=factors_train)

model4.hierarchical_clustering_estimator_.plot_dendrogram(heatmap=True)
```

<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>[plotly figure stripped from llms output]
<br />
<br />

To compare the models, we use an equal weighted benchmark using
the [`EqualWeighted`](https://skfolio.org/generated/skfolio.optimization.EqualWeighted.html.md#skfolio.optimization.EqualWeighted) estimator:

```Python
bench = EqualWeighted()
bench.fit(X_train)
bench.weights_
```

```none
array([0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
       0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05])
```

<a id="prediction"></a>

## Prediction

We predict the models and the benchmark on the test set:

```Python
population_test = Population([])
for model in [model1, model2, model3, model4, bench]:
    population_test.append(model.predict(X_test))

population_test.plot_cumulative_returns()
```

<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>[plotly figure stripped from llms output]
<br />
<br />

<a id="composition"></a>

## Composition

From the below composition, we notice that all models are relatively close to each
other, as explained earlier:

```Python
population_test.plot_composition()
```

<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>[plotly figure stripped from llms output]
<br />
<br />

<a id="summary"></a>

## Summary

Finally, let’s print the summary statistics:

```Python
summary = population_test.summary()
summary.loc["Annualized Sharpe Ratio"]
```

```none
HRP-CVaR-Ward-Pearson      0.86
HRP-CVaR-Single-Pearson    0.84
HRP-CVaR-Ward-Kendal       0.86
HRP-CVaR-Factor-Model      0.87
EqualWeighted              0.86
Name: Annualized Sharpe Ratio, dtype: str
```

```Python
summary
```

<div class="output_subarea output_html rendered_html output_result">
<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>HRP-CVaR-Ward-Pearson</th>
      <th>HRP-CVaR-Single-Pearson</th>
      <th>HRP-CVaR-Ward-Kendal</th>
      <th>HRP-CVaR-Factor-Model</th>
      <th>EqualWeighted</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Mean</th>
      <td>0.081%</td>
      <td>0.079%</td>
      <td>0.079%</td>
      <td>0.081%</td>
      <td>0.084%</td>
    </tr>
    <tr>
      <th>Annualized Mean</th>
      <td>20.41%</td>
      <td>19.81%</td>
      <td>19.95%</td>
      <td>20.29%</td>
      <td>21.27%</td>
    </tr>
    <tr>
      <th>Variance</th>
      <td>0.00022</td>
      <td>0.00022</td>
      <td>0.00022</td>
      <td>0.00022</td>
      <td>0.00024</td>
    </tr>
    <tr>
      <th>Annualized Variance</th>
      <td>5.62%</td>
      <td>5.51%</td>
      <td>5.42%</td>
      <td>5.47%</td>
      <td>6.13%</td>
    </tr>
    <tr>
      <th>Semi-Variance</th>
      <td>0.00011</td>
      <td>0.00011</td>
      <td>0.00011</td>
      <td>0.00011</td>
      <td>0.00012</td>
    </tr>
    <tr>
      <th>Annualized Semi-Variance</th>
      <td>2.89%</td>
      <td>2.82%</td>
      <td>2.78%</td>
      <td>2.78%</td>
      <td>3.11%</td>
    </tr>
    <tr>
      <th>Standard Deviation</th>
      <td>1.49%</td>
      <td>1.48%</td>
      <td>1.47%</td>
      <td>1.47%</td>
      <td>1.56%</td>
    </tr>
    <tr>
      <th>Annualized Standard Deviation</th>
      <td>23.71%</td>
      <td>23.48%</td>
      <td>23.29%</td>
      <td>23.38%</td>
      <td>24.75%</td>
    </tr>
    <tr>
      <th>Semi-Deviation</th>
      <td>1.07%</td>
      <td>1.06%</td>
      <td>1.05%</td>
      <td>1.05%</td>
      <td>1.11%</td>
    </tr>
    <tr>
      <th>Annualized Semi-Deviation</th>
      <td>16.99%</td>
      <td>16.78%</td>
      <td>16.69%</td>
      <td>16.66%</td>
      <td>17.63%</td>
    </tr>
    <tr>
      <th>Mean Absolute Deviation</th>
      <td>0.93%</td>
      <td>0.92%</td>
      <td>0.91%</td>
      <td>0.92%</td>
      <td>0.99%</td>
    </tr>
    <tr>
      <th>CVaR at 95%</th>
      <td>3.51%</td>
      <td>3.44%</td>
      <td>3.43%</td>
      <td>3.42%</td>
      <td>3.65%</td>
    </tr>
    <tr>
      <th>EVaR at 95%</th>
      <td>6.51%</td>
      <td>6.51%</td>
      <td>6.47%</td>
      <td>6.39%</td>
      <td>6.58%</td>
    </tr>
    <tr>
      <th>Worst Realization</th>
      <td>10.64%</td>
      <td>10.70%</td>
      <td>10.66%</td>
      <td>10.50%</td>
      <td>10.77%</td>
    </tr>
    <tr>
      <th>CDaR at 95%</th>
      <td>17.37%</td>
      <td>17.36%</td>
      <td>16.94%</td>
      <td>17.78%</td>
      <td>18.54%</td>
    </tr>
    <tr>
      <th>MAX Drawdown</th>
      <td>35.36%</td>
      <td>34.19%</td>
      <td>33.56%</td>
      <td>34.03%</td>
      <td>34.70%</td>
    </tr>
    <tr>
      <th>Average Drawdown</th>
      <td>3.00%</td>
      <td>3.14%</td>
      <td>3.05%</td>
      <td>3.28%</td>
      <td>3.38%</td>
    </tr>
    <tr>
      <th>EDaR at 95%</th>
      <td>24.28%</td>
      <td>23.72%</td>
      <td>23.32%</td>
      <td>23.86%</td>
      <td>24.47%</td>
    </tr>
    <tr>
      <th>First Lower Partial Moment</th>
      <td>0.46%</td>
      <td>0.46%</td>
      <td>0.46%</td>
      <td>0.46%</td>
      <td>0.50%</td>
    </tr>
    <tr>
      <th>Ulcer Index</th>
      <td>0.053</td>
      <td>0.054</td>
      <td>0.052</td>
      <td>0.056</td>
      <td>0.058</td>
    </tr>
    <tr>
      <th>Gini Mean Difference</th>
      <td>1.42%</td>
      <td>1.40%</td>
      <td>1.40%</td>
      <td>1.41%</td>
      <td>1.51%</td>
    </tr>
    <tr>
      <th>Value at Risk at 95%</th>
      <td>2.02%</td>
      <td>1.93%</td>
      <td>1.97%</td>
      <td>1.97%</td>
      <td>2.15%</td>
    </tr>
    <tr>
      <th>Drawdown at Risk at 95%</th>
      <td>10.14%</td>
      <td>10.90%</td>
      <td>10.35%</td>
      <td>11.49%</td>
      <td>12.03%</td>
    </tr>
    <tr>
      <th>Entropic Risk Measure at 95%</th>
      <td>3.00</td>
      <td>3.00</td>
      <td>3.00</td>
      <td>3.00</td>
      <td>3.00</td>
    </tr>
    <tr>
      <th>Fourth Central Moment</th>
      <td>0.000079%</td>
      <td>0.000078%</td>
      <td>0.000073%</td>
      <td>0.000074%</td>
      <td>0.000090%</td>
    </tr>
    <tr>
      <th>Fourth Lower Partial Moment</th>
      <td>0.000041%</td>
      <td>0.000040%</td>
      <td>0.000039%</td>
      <td>0.000037%</td>
      <td>0.000043%</td>
    </tr>
    <tr>
      <th>Skew</th>
      <td>-8.53%</td>
      <td>-6.33%</td>
      <td>-11.58%</td>
      <td>-1.42%</td>
      <td>4.61%</td>
    </tr>
    <tr>
      <th>Kurtosis</th>
      <td>1593.00%</td>
      <td>1634.75%</td>
      <td>1581.88%</td>
      <td>1569.59%</td>
      <td>1530.96%</td>
    </tr>
    <tr>
      <th>Sharpe Ratio</th>
      <td>0.054</td>
      <td>0.053</td>
      <td>0.054</td>
      <td>0.055</td>
      <td>0.054</td>
    </tr>
    <tr>
      <th>Annualized Sharpe Ratio</th>
      <td>0.86</td>
      <td>0.84</td>
      <td>0.86</td>
      <td>0.87</td>
      <td>0.86</td>
    </tr>
    <tr>
      <th>Sortino Ratio</th>
      <td>0.076</td>
      <td>0.074</td>
      <td>0.075</td>
      <td>0.077</td>
      <td>0.076</td>
    </tr>
    <tr>
      <th>Annualized Sortino Ratio</th>
      <td>1.20</td>
      <td>1.18</td>
      <td>1.20</td>
      <td>1.22</td>
      <td>1.21</td>
    </tr>
    <tr>
      <th>Mean Absolute Deviation Ratio</th>
      <td>0.087</td>
      <td>0.086</td>
      <td>0.087</td>
      <td>0.087</td>
      <td>0.085</td>
    </tr>
    <tr>
      <th>First Lower Partial Moment Ratio</th>
      <td>0.17</td>
      <td>0.17</td>
      <td>0.17</td>
      <td>0.17</td>
      <td>0.17</td>
    </tr>
    <tr>
      <th>Value at Risk Ratio at 95%</th>
      <td>0.040</td>
      <td>0.041</td>
      <td>0.040</td>
      <td>0.041</td>
      <td>0.039</td>
    </tr>
    <tr>
      <th>CVaR Ratio at 95%</th>
      <td>0.023</td>
      <td>0.023</td>
      <td>0.023</td>
      <td>0.024</td>
      <td>0.023</td>
    </tr>
    <tr>
      <th>Entropic Risk Measure Ratio at 95%</th>
      <td>0.00027</td>
      <td>0.00026</td>
      <td>0.00026</td>
      <td>0.00027</td>
      <td>0.00028</td>
    </tr>
    <tr>
      <th>EVaR Ratio at 95%</th>
      <td>0.012</td>
      <td>0.012</td>
      <td>0.012</td>
      <td>0.013</td>
      <td>0.013</td>
    </tr>
    <tr>
      <th>Worst Realization Ratio</th>
      <td>0.0076</td>
      <td>0.0073</td>
      <td>0.0074</td>
      <td>0.0077</td>
      <td>0.0078</td>
    </tr>
    <tr>
      <th>Drawdown at Risk Ratio at 95%</th>
      <td>0.0080</td>
      <td>0.0072</td>
      <td>0.0076</td>
      <td>0.0070</td>
      <td>0.0070</td>
    </tr>
    <tr>
      <th>CDaR Ratio at 95%</th>
      <td>0.0047</td>
      <td>0.0045</td>
      <td>0.0047</td>
      <td>0.0045</td>
      <td>0.0046</td>
    </tr>
    <tr>
      <th>Calmar Ratio</th>
      <td>0.0023</td>
      <td>0.0023</td>
      <td>0.0024</td>
      <td>0.0024</td>
      <td>0.0024</td>
    </tr>
    <tr>
      <th>Average Drawdown Ratio</th>
      <td>0.027</td>
      <td>0.025</td>
      <td>0.026</td>
      <td>0.025</td>
      <td>0.025</td>
    </tr>
    <tr>
      <th>EDaR Ratio at 95%</th>
      <td>0.0033</td>
      <td>0.0033</td>
      <td>0.0034</td>
      <td>0.0034</td>
      <td>0.0034</td>
    </tr>
    <tr>
      <th>Ulcer Index Ratio</th>
      <td>0.015</td>
      <td>0.015</td>
      <td>0.015</td>
      <td>0.014</td>
      <td>0.015</td>
    </tr>
    <tr>
      <th>Gini Mean Difference Ratio</th>
      <td>0.057</td>
      <td>0.056</td>
      <td>0.057</td>
      <td>0.057</td>
      <td>0.056</td>
    </tr>
    <tr>
      <th>Effective Number of Assets</th>
      <td>17.56017723500113</td>
      <td>17.30105753780178</td>
      <td>17.533289375090764</td>
      <td>17.272263586429105</td>
      <td>19.999999999999993</td>
    </tr>
    <tr>
      <th>Assets Number</th>
      <td>20</td>
      <td>20</td>
      <td>20</td>
      <td>20</td>
      <td>20</td>
    </tr>
  </tbody>
</table>
</div>
</div>
<br />
<br />

**Total running time of the script:** (0 minutes 3.067 seconds)

<a id="sphx-glr-download-auto-examples-clustering-plot-1-hrp-cvar-py"></a>
