Hierarchical Clustering Plot
When to Use
Use this skill when you need a sample-level hierarchical clustering dendrogram from a bulk expression matrix and a sample annotation table.
- Good fits: sample QC, batch inspection, sample similarity assessment, checking whether annotated sample groups cluster as expected.
- Trigger keywords: hierarchical clustering, dendrogram, sample QC, batch inspection, sample similarity.
- Not for: differential expression testing, gene clustering heatmaps, single-cell clustering workflows.
When to Read External Files
| Situation |
File to Read |
Purpose |
| Need algorithm details |
references/algorithm.md |
Distance calculation, linkage rules, and clustering assumptions |
| Need to run analysis or inspect CLI entrypoint behavior |
scripts/main.R |
Execute the workflow and inspect argument parsing, defaults, required flags, and sourced modules |
| Need workflow implementation details |
scripts/run_analysis.R |
See orchestration order, temp workspace handling, and output generation |
| Need logging or warning behavior |
scripts/logging_utils.R |
See standardized console log formatting and memory usage messages |
| Need file or parameter validation details |
scripts/validation_utils.R |
See path checks, output-directory checks, and scalar validation |
| Need timeout, temp workspace, or session info behavior |
scripts/runtime_utils.R |
See timeout control, temp cleanup, output copying, and session-info export |
| Need expression/group input handling |
scripts/input_functions.R |
See CSV loading, sample matching, and label extraction |
| Need clustering logic |
scripts/clustering_functions.R |
See distance calculation and hclust() generation |
| Need output-writing logic |
scripts/output_utils.R |
See CSV export and PDF rendering |
| Encounter errors, warnings, or unexpected clustering patterns |
references/troubleshooting.md |
Common failures, warning follow-up, and interpretation guidance |
| Need CLI examples or common parameter combinations |
references/cli-guide.md |
Detailed command patterns for standard, variant, and test runs |
| Need example input files or schema-concrete fixtures |
tests/data/ |
Inspect sample CSV layouts for expression and group inputs |
| Need expected output names or artifact formats |
## Output Files and references/cli-guide.md |
Confirm the files the workflow writes and inspect documented example previews |
| Need to run regression tests |
tests/run_tests.R |
Execute the automated test suite |
| Need exact test assertions or edge cases |
tests/testthat/test-clustering.R |
Inspect validation, reproducibility, and output checks |
Usage
Rscript scripts/main.R \
--input_file ./expression_matrix.csv \
--group_file ./sample_groups.csv \
--output_dir ./output/ \
--distance_method euclidean \
--linkage_method complete \
--label_column batch \
--timeout_seconds 300 \
--seed 42
Arguments
| Short |
Long |
Type |
Default |
Description |
-i |
--input_file |
character |
required |
Expression matrix file (features as rows, samples as columns) |
-g |
--group_file |
character |
required |
Sample annotation file (first column sample ID, one metadata column for labels) |
-o |
--output_dir |
character |
./output/ |
Output directory |
-d |
--distance_method |
character |
euclidean |
Distance metric for dist(): euclidean, maximum, manhattan, canberra, binary, minkowski |
-m |
--linkage_method |
character |
complete |
Linkage method for hclust(): complete, single, average, mcquitty, median, centroid, ward.D, ward.D2 |
-l |
--label_column |
character |
second column |
Column used as dendrogram labels |
-c |
--label_cex |
numeric |
0.8 |
Dendrogram label size, must be > 0 |
-t |
--timeout_seconds |
integer |
300 |
Elapsed time limit in seconds, must be > 0 |
-s |
--seed |
integer |
42 |
Random seed for reproducibility |
Input Format
Expression Matrix (input_file)
Features as rows, samples as columns, CSV format with feature IDs in the first column.
,Sample01,Sample02,Sample03
TSPAN6,1.847876677,1.831755661,3.827625975
TNMD,0.034919984,0.053250385,1.388850793
Requirements:
- The first column contains unique feature IDs.
- All sample columns must be numeric.
- Sample column names must be unique and non-empty.
- At least two matched samples are required.
Sample Annotation (group_file)
CSV with sample IDs in the first column. The second column is used by default for leaf labels unless --label_column is provided.
sample,batch
Sample01,batch1
Sample02,batch2
Sample03,batch1
Requirements:
- Sample IDs must match expression matrix column names exactly.
- The selected label column must exist and contain no empty values.
- The file must contain at least one metadata column in addition to sample IDs.
Output Files
| File |
Description |
hierarchical_clustering_plot.pdf |
Sample dendrogram plot |
sample_distance_matrix.csv |
Pairwise sample distance matrix |
clustering_order.csv |
Leaf order shown in the dendrogram |
matched_samples.csv |
Sample-to-label table used for plotting |
session_info.txt |
R session and package version info |
Workflow
Step 1: Validate Input
WHEN checking file or parameter validation, READ: scripts/validation_utils.R
WHEN checking expression/group CSV handling, READ: scripts/input_functions.R
- Check file existence
- Reject empty files before parsing
- Read the expression matrix and sample annotation CSV files
- Validate required columns, unique IDs, and numeric expression values
Step 2: Align Samples
WHEN checking sample matching logic, READ: scripts/input_functions.R
- Match sample IDs between the annotation file and expression matrix
- Reorder matrix columns to the annotation file order
- Select the label column used for plotting
Step 3: Build Hierarchical Clustering
WHEN interpreting distance or linkage behavior, READ: references/algorithm.md
WHEN checking clustering implementation, READ: scripts/clustering_functions.R
- Transpose the expression matrix to sample-by-feature form
- Compute pairwise sample distances with
dist()
- Build the dendrogram with
hclust()
Step 4: Save Outputs
WHEN checking output staging and cleanup behavior, READ: scripts/run_analysis.R
WHEN checking PDF/CSV export behavior, READ: scripts/output_utils.R
WHEN checking timeout, session info, or final file copy behavior, READ: scripts/runtime_utils.R
- Stage outputs in a temporary workspace
- Export the pairwise distance matrix
- Export the plotted leaf order
- Render the dendrogram as PDF
- Copy finalized outputs into the requested output directory
Methods
Distance Matrix
Sample distances are computed from the transposed expression matrix using base R dist().
Hierarchical Clustering
The clustering tree is built with base R hclust(). The default linkage method is complete, matching the source analysis script.
Examples
Basic Usage
Rscript scripts/main.R \
-i tests/data/sample_expression_matrix.csv \
-g tests/data/sample_groups.csv \
-o ./output/ \
-t 300
Use Sample IDs as Labels
Rscript scripts/main.R \
-i tests/data/sample_expression_matrix.csv \
-g tests/data/sample_groups.csv \
-o ./output_sample_labels/ \
-l sample
Use Average Linkage
Rscript scripts/main.R \
-i tests/data/sample_expression_matrix.csv \
-g tests/data/sample_groups.csv \
-o ./output_average/ \
-m average
Error Handling
Common Errors
| Error |
Cause |
Solution |
Read More |
SKILL_DEPENDENCY_MISSING |
Required R package is not installed |
Install the missing package and rerun |
references/troubleshooting.md#skill_dependency_missing |
SKILL_FILE_NOT_FOUND |
Input file does not exist or output directory could not be created |
Check the path and permissions |
references/troubleshooting.md#skill_file_not_found |
SKILL_EMPTY_FILE |
Input file is empty |
Re-export the CSV and confirm it contains data |
references/troubleshooting.md#skill_empty_file |
SKILL_EMPTY_DATA |
CSV parsed successfully but contains no data rows |
Confirm the CSV has at least one data row |
references/troubleshooting.md#skill_empty_data |
SKILL_PARSE_ERROR |
CSV parsing failed |
Check encoding, delimiters, and CSV structure |
references/troubleshooting.md#skill_parse_error |
SKILL_MISSING_COLUMNS |
Expected columns or headers are missing |
Check CSV headers and metadata columns |
references/troubleshooting.md#skill_missing_columns |
SKILL_INVALID_TYPE |
Expression values or parameters have the wrong type |
Ensure numeric fields are numeric |
references/troubleshooting.md#skill_invalid_type |
SKILL_SAMPLE_MISMATCH |
Sample IDs do not match |
Ensure the first column in group_file matches matrix column names |
references/troubleshooting.md#skill_sample_mismatch |
SKILL_INVALID_DATA |
Expression or annotation data is malformed |
Check duplicate IDs, missing labels, and numeric values |
references/troubleshooting.md#skill_invalid_data |
SKILL_INVALID_PARAMETER |
Unsupported distance, linkage, or label parameter |
Use one of the documented parameter values |
references/troubleshooting.md#skill_invalid_parameter |
SKILL_TIMEOUT |
Analysis exceeded the time limit |
Increase --timeout_seconds and rerun |
references/troubleshooting.md#skill_timeout |
SKILL_PLOT_ERROR |
Plot device failed while writing PDF |
Check output directory permissions and rerun |
references/troubleshooting.md#skill_plot_error |
SKILL_WRITE_ERROR |
Output or intermediate files could not be written |
Check output directory permissions and free disk space |
references/troubleshooting.md#skill_write_error |
SKILL_WARNING |
Non-fatal warning occurred during execution |
Inspect console warnings and verify output quality |
references/troubleshooting.md#skill_warning |
SKILL_MEMORY_WARNING |
Memory usage exceeded the warning threshold |
Reduce input size or rerun with more memory |
references/troubleshooting.md#skill_memory_warning |
IF error persists, READ: references/troubleshooting.md
Testing
Test with Sample Data
# Check help
Rscript scripts/main.R --help
# Run with sample data
Rscript scripts/main.R \
-i tests/data/sample_expression_matrix.csv \
-g tests/data/sample_groups.csv \
-o ./output/
# Run unit tests (requires testthat and data.table)
Rscript tests/run_tests.R
Validation Commands
# Check main output plot exists
ls -la ./output/hierarchical_clustering_plot.pdf
# Inspect clustering order
wc -l ./output/clustering_order.csv
Implementation Checklist
Last updated: 2026-04-16 | Version: 1.0.0
1---2name: hierarchical-clustering-plot3description: Use when building a sample-level hierarchical clustering dendrogram from a bulk expression matrix and sample annotation table, especially for QC, batch inspection, or sample similarity assessment. Trigger keywords: hierarchical clustering, dendrogram, sample QC, batch inspection, sample similarity. NOT for: differential expression testing, gene clustering heatmaps, single-cell clustering workflows.4---5
6# Hierarchical Clustering Plot
7
8## When to Use
9
10Use this skill when you need a sample-level hierarchical clustering dendrogram from a bulk expression matrix and a sample annotation table.
11
12- Good fits: sample QC, batch inspection, sample similarity assessment, checking whether annotated sample groups cluster as expected.
13- Trigger keywords: hierarchical clustering, dendrogram, sample QC, batch inspection, sample similarity.
14- Not for: differential expression testing, gene clustering heatmaps, single-cell clustering workflows.
15
16## When to Read External Files
17
18| Situation | File to Read | Purpose |
19|-----------|--------------|---------|
20| **Need algorithm details** | `references/algorithm.md` | Distance calculation, linkage rules, and clustering assumptions |
21| **Need to run analysis or inspect CLI entrypoint behavior** | `scripts/main.R` | Execute the workflow and inspect argument parsing, defaults, required flags, and sourced modules |
22| **Need workflow implementation details** | `scripts/run_analysis.R` | See orchestration order, temp workspace handling, and output generation |
23| **Need logging or warning behavior** | `scripts/logging_utils.R` | See standardized console log formatting and memory usage messages |
24| **Need file or parameter validation details** | `scripts/validation_utils.R` | See path checks, output-directory checks, and scalar validation |
25| **Need timeout, temp workspace, or session info behavior** | `scripts/runtime_utils.R` | See timeout control, temp cleanup, output copying, and session-info export |
26| **Need expression/group input handling** | `scripts/input_functions.R` | See CSV loading, sample matching, and label extraction |
27| **Need clustering logic** | `scripts/clustering_functions.R` | See distance calculation and `hclust()` generation |
28| **Need output-writing logic** | `scripts/output_utils.R` | See CSV export and PDF rendering |
29| **Encounter errors, warnings, or unexpected clustering patterns** | `references/troubleshooting.md` | Common failures, warning follow-up, and interpretation guidance |
30| **Need CLI examples or common parameter combinations** | `references/cli-guide.md` | Detailed command patterns for standard, variant, and test runs |
31| **Need example input files or schema-concrete fixtures** | `tests/data/` | Inspect sample CSV layouts for expression and group inputs |
32| **Need expected output names or artifact formats** | `## Output Files` and `references/cli-guide.md` | Confirm the files the workflow writes and inspect documented example previews |
33| **Need to run regression tests** | `tests/run_tests.R` | Execute the automated test suite |
34| **Need exact test assertions or edge cases** | `tests/testthat/test-clustering.R` | Inspect validation, reproducibility, and output checks |
35
36---
37
38## Usage
39
40```bash
41Rscript scripts/main.R \
42 --input_file ./expression_matrix.csv \
43 --group_file ./sample_groups.csv \
44 --output_dir ./output/ \
45 --distance_method euclidean \
46 --linkage_method complete \
47 --label_column batch \
48 --timeout_seconds 300 \
49 --seed 42
50```
51
52---
53
54## Arguments
55
56| Short | Long | Type | Default | Description |
57|-------|------|------|---------|-------------|
58| `-i` | `--input_file` | character | **required** | Expression matrix file (features as rows, samples as columns) |
59| `-g` | `--group_file` | character | **required** | Sample annotation file (first column sample ID, one metadata column for labels) |
60| `-o` | `--output_dir` | character | `./output/` | Output directory |
61| `-d` | `--distance_method` | character | `euclidean` | Distance metric for `dist()`: euclidean, maximum, manhattan, canberra, binary, minkowski |
62| `-m` | `--linkage_method` | character | `complete` | Linkage method for `hclust()`: complete, single, average, mcquitty, median, centroid, ward.D, ward.D2 |
63| `-l` | `--label_column` | character | second column | Column used as dendrogram labels |
64| `-c` | `--label_cex` | numeric | `0.8` | Dendrogram label size, must be `> 0` |
65| `-t` | `--timeout_seconds` | integer | `300` | Elapsed time limit in seconds, must be `> 0` |
66| `-s` | `--seed` | integer | `42` | Random seed for reproducibility |
67
68---
69
70## Input Format
71
72### Expression Matrix (`input_file`)
73
74Features as rows, samples as columns, CSV format with feature IDs in the first column.
75
76```csv
77,Sample01,Sample02,Sample03
78TSPAN6,1.847876677,1.831755661,3.827625975
79TNMD,0.034919984,0.053250385,1.388850793
80```
81
82**Requirements:**
83- The first column contains unique feature IDs.
84- All sample columns must be numeric.
85- Sample column names must be unique and non-empty.
86- At least two matched samples are required.
87
88### Sample Annotation (`group_file`)
89
90CSV with sample IDs in the first column. The second column is used by default for leaf labels unless `--label_column` is provided.
91
92```csv
93sample,batch
94Sample01,batch1
95Sample02,batch2
96Sample03,batch1
97```
98
99**Requirements:**
100- Sample IDs must match expression matrix column names exactly.
101- The selected label column must exist and contain no empty values.
102- The file must contain at least one metadata column in addition to sample IDs.
103
104---
105
106## Output Files
107
108| File | Description |
109|------|-------------|
110| `hierarchical_clustering_plot.pdf` | Sample dendrogram plot |
111| `sample_distance_matrix.csv` | Pairwise sample distance matrix |
112| `clustering_order.csv` | Leaf order shown in the dendrogram |
113| `matched_samples.csv` | Sample-to-label table used for plotting |
114| `session_info.txt` | R session and package version info |
115
116## Workflow
117
118### Step 1: Validate Input
119**WHEN checking file or parameter validation**, READ: `scripts/validation_utils.R`
120
121**WHEN checking expression/group CSV handling**, READ: `scripts/input_functions.R`
122
123- Check file existence
124- Reject empty files before parsing
125- Read the expression matrix and sample annotation CSV files
126- Validate required columns, unique IDs, and numeric expression values
127
128### Step 2: Align Samples
129**WHEN checking sample matching logic**, READ: `scripts/input_functions.R`
130
131- Match sample IDs between the annotation file and expression matrix
132- Reorder matrix columns to the annotation file order
133- Select the label column used for plotting
134
135### Step 3: Build Hierarchical Clustering
136**WHEN interpreting distance or linkage behavior**, READ: `references/algorithm.md`
137
138**WHEN checking clustering implementation**, READ: `scripts/clustering_functions.R`
139
140- Transpose the expression matrix to sample-by-feature form
141- Compute pairwise sample distances with `dist()`
142- Build the dendrogram with `hclust()`
143
144### Step 4: Save Outputs
145**WHEN checking output staging and cleanup behavior**, READ: `scripts/run_analysis.R`
146
147**WHEN checking PDF/CSV export behavior**, READ: `scripts/output_utils.R`
148
149**WHEN checking timeout, session info, or final file copy behavior**, READ: `scripts/runtime_utils.R`
150
151- Stage outputs in a temporary workspace
152- Export the pairwise distance matrix
153- Export the plotted leaf order
154- Render the dendrogram as PDF
155- Copy finalized outputs into the requested output directory
156
157---
158
159## Methods
160
161### Distance Matrix
162Sample distances are computed from the transposed expression matrix using base R `dist()`.
163
164### Hierarchical Clustering
165The clustering tree is built with base R `hclust()`. The default linkage method is `complete`, matching the source analysis script.
166
167---
168
169## Examples
170
171### Basic Usage
172```bash
173Rscript scripts/main.R \
174 -i tests/data/sample_expression_matrix.csv \
175 -g tests/data/sample_groups.csv \
176 -o ./output/ \
177 -t 300
178```
179
180### Use Sample IDs as Labels
181```bash
182Rscript scripts/main.R \
183 -i tests/data/sample_expression_matrix.csv \
184 -g tests/data/sample_groups.csv \
185 -o ./output_sample_labels/ \
186 -l sample
187```
188
189### Use Average Linkage
190```bash
191Rscript scripts/main.R \
192 -i tests/data/sample_expression_matrix.csv \
193 -g tests/data/sample_groups.csv \
194 -o ./output_average/ \
195 -m average
196```
197
198---
199
200## Error Handling
201
202### Common Errors
203
204| Error | Cause | Solution | Read More |
205|-------|-------|----------|-----------|
206| `SKILL_DEPENDENCY_MISSING` | Required R package is not installed | Install the missing package and rerun | `references/troubleshooting.md#skill_dependency_missing` |
207| `SKILL_FILE_NOT_FOUND` | Input file does not exist or output directory could not be created | Check the path and permissions | `references/troubleshooting.md#skill_file_not_found` |
208| `SKILL_EMPTY_FILE` | Input file is empty | Re-export the CSV and confirm it contains data | `references/troubleshooting.md#skill_empty_file` |
209| `SKILL_EMPTY_DATA` | CSV parsed successfully but contains no data rows | Confirm the CSV has at least one data row | `references/troubleshooting.md#skill_empty_data` |
210| `SKILL_PARSE_ERROR` | CSV parsing failed | Check encoding, delimiters, and CSV structure | `references/troubleshooting.md#skill_parse_error` |
211| `SKILL_MISSING_COLUMNS` | Expected columns or headers are missing | Check CSV headers and metadata columns | `references/troubleshooting.md#skill_missing_columns` |
212| `SKILL_INVALID_TYPE` | Expression values or parameters have the wrong type | Ensure numeric fields are numeric | `references/troubleshooting.md#skill_invalid_type` |
213| `SKILL_SAMPLE_MISMATCH` | Sample IDs do not match | Ensure the first column in `group_file` matches matrix column names | `references/troubleshooting.md#skill_sample_mismatch` |
214| `SKILL_INVALID_DATA` | Expression or annotation data is malformed | Check duplicate IDs, missing labels, and numeric values | `references/troubleshooting.md#skill_invalid_data` |
215| `SKILL_INVALID_PARAMETER` | Unsupported distance, linkage, or label parameter | Use one of the documented parameter values | `references/troubleshooting.md#skill_invalid_parameter` |
216| `SKILL_TIMEOUT` | Analysis exceeded the time limit | Increase `--timeout_seconds` and rerun | `references/troubleshooting.md#skill_timeout` |
217| `SKILL_PLOT_ERROR` | Plot device failed while writing PDF | Check output directory permissions and rerun | `references/troubleshooting.md#skill_plot_error` |
218| `SKILL_WRITE_ERROR` | Output or intermediate files could not be written | Check output directory permissions and free disk space | `references/troubleshooting.md#skill_write_error` |
219| `SKILL_WARNING` | Non-fatal warning occurred during execution | Inspect console warnings and verify output quality | `references/troubleshooting.md#skill_warning` |
220| `SKILL_MEMORY_WARNING` | Memory usage exceeded the warning threshold | Reduce input size or rerun with more memory | `references/troubleshooting.md#skill_memory_warning` |
221
222**IF error persists**, READ: `references/troubleshooting.md`
223
224---
225
226## Testing
227
228### Test with Sample Data
229
230```bash
231# Check help
232Rscript scripts/main.R --help
233
234# Run with sample data
235Rscript scripts/main.R \
236 -i tests/data/sample_expression_matrix.csv \
237 -g tests/data/sample_groups.csv \
238 -o ./output/
239
240# Run unit tests (requires testthat and data.table)
241Rscript tests/run_tests.R
242```
243
244### Validation Commands
245
246```bash
247# Check main output plot exists
248ls -la ./output/hierarchical_clustering_plot.pdf
249
250# Inspect clustering order
251wc -l ./output/clustering_order.csv
252```
253
254## Implementation Checklist
255
256- [x] CLI parsing with `optparse`
257- [x] `set.seed()` for reproducibility
258- [x] Input validation (file existence, emptiness, types, required columns)
259- [x] Try-catch based fatal error handling
260- [x] Standardized `SKILL_*` error classification
261- [x] Timeout control with `setTimeLimit()`
262- [x] Standardized console-only logging
263- [x] Base R clustering implementation
264- [x] Session info recording with `sink()`
265- [x] Temporary workspace cleanup with `on.exit()`
266- [x] Memory usage reporting with `gc()`
267- [x] File reading instructions in SKILL.md
268- [x] Modular script structure across `scripts/`
269- [x] Test template added under `tests/testthat/`
270- [x] Test data provided
271- [x] Error handling with `SKILL_*` codes
272- [x] `get_script_dir()` defined before use
273- [x] Scripts in `scripts/` directory
274- [x] References in `references/` directory
275
276---
277
278*Last updated: 2026-04-16 | Version: 1.0.0*