This is the multi-page printable view of this section.
Click here to print.
Return to the regular view of this page.
Query Expression Language
The W&B Query Expression Language lets you programmatically analyze and visualize your ML experiments directly in the W&B UI. Transform raw experiment data into actionable insights using powerful query operations.
Important: Where Query Expressions Run
Query Expressions are NOT local code! They are typed directly into the W&B web interface, not in your Python/JavaScript files.
Getting Started
Step 1: Log Data to W&B (Local Code)
First, you need data in W&B to query. This requires the W&B Python SDK:
pip install wandb # Only installation needed - for logging data
# your_training_script.py - runs locally
import wandb
wandb.init(project="my-ml-project")
wandb.log({"loss": 0.5, "accuracy": 0.85})
wandb.finish()
Step 2: Query Your Data (W&B Web UI)
After logging runs, analyze them in the W&B web interface:
- Open your browser and go to wandb.ai
- Navigate to your project (e.g.,
wandb.ai/your-username/my-ml-project
)
- Click “+ Add Panel” → Select “Query Panel”
- Type expressions in the web editor (NOT in your local code):
// This is typed into the wandb.ai interface
runs.map(r => runSummary(r).accuracy).avg()
- See results instantly as charts or tables in your browser
Complete Example: Finding Your Best Model
Here’s what you would type in the W&B Query Panel editor to analyze a hyperparameter sweep:
// Remember: This is typed into the Query Panel at wandb.ai
// NOT in your local code files!
// Step 1: Filter to successful runs from your latest sweep
const validRuns = runs
.filter(r => r.state === "finished")
.filter(r => runConfig(r).sweep_id === "sweep_2024_01")
// Step 2: Extract key metrics and configurations
const runAnalysis = validRuns.map(r => ({
name: r.name,
accuracy: runSummary(r).best_accuracy,
loss: runSummary(r).final_loss,
learning_rate: runConfig(r).learning_rate,
batch_size: runConfig(r).batch_size,
training_time: r.duration
}))
// Step 3: Find the best run
const bestRun = validRuns
.reduce((best, current) =>
runSummary(current).best_accuracy > runSummary(best).best_accuracy
? current
: best
)
// Step 4: Calculate statistics across all runs
const stats = {
avg_accuracy: validRuns.map(r => runSummary(r).best_accuracy).avg(),
std_accuracy: validRuns.map(r => runSummary(r).best_accuracy).std(),
total_compute_hours: validRuns.map(r => r.duration).sum() / 3600
}
// Step 5: Group by hyperparameter to find optimal values
const byLearningRate = validRuns
.groupby(r => runConfig(r).learning_rate)
.map(group => ({
lr: group.key,
avg_accuracy: group.values.map(r => runSummary(r).best_accuracy).avg(),
num_runs: group.values.length
}))
Core Concepts
Chainable Operations
All operations can be chained together for powerful data transformations:
runs
.filter(/* select runs */)
.map(/* transform data */)
.groupby(/* organize results */)
.sort(/* order output */)
Type Safety
The expression language is fully typed, providing autocomplete and validation as you write queries.
Functions for querying and manipulating W&B data:
Core type definitions:
Common Patterns
The following examples show Query Expressions you would type in the W&B web UI:
Compare Model Architectures
// Type this in the Query Panel at wandb.ai
// Group runs by model type and compare average performance
runs
.groupby(r => runConfig(r).model_type)
.map(g => ({
model: g.key,
avg_accuracy: g.values.map(r => runSummary(r).accuracy).avg(),
best_accuracy: g.values.map(r => runSummary(r).accuracy).max(),
training_hours: g.values.map(r => r.duration).sum() / 3600
}))
.sort((a, b) => b.avg_accuracy - a.avg_accuracy)
Track Experiment Progress
// Monitor ongoing experiments
runs
.filter(r => r.state === "running")
.map(r => ({
name: r.name,
progress: runSummary(r).epoch / runConfig(r).total_epochs,
current_loss: runSummary(r).loss,
eta_minutes: (r.duration / runSummary(r).epoch) *
(runConfig(r).total_epochs - runSummary(r).epoch) / 60
}))
Find Optimal Hyperparameters
// Identify best performing hyperparameter combinations
runs
.filter(r => runSummary(r).val_accuracy > 0.85)
.map(r => ({
accuracy: runSummary(r).val_accuracy,
lr: runConfig(r).learning_rate,
batch_size: runConfig(r).batch_size,
optimizer: runConfig(r).optimizer
}))
.sort((a, b) => b.accuracy - a.accuracy)
.slice(0, 10) // Top 10 configurations
See Also
1.1 - Artifact
W&B artifact for versioning datasets, models, and other files.
const artifact: Artifact = {
id: "artifact_abc123",
name: "model-weights",
type: artifactType,
description: "Trained model weights",
aliases: ["latest", "production"],
createdAt: new Date("2024-01-15")
};
Property |
Type |
Description |
id |
string |
Artifact ID |
name |
string |
Artifact name |
type |
ArtifactType |
Artifact type |
description |
string |
Optional. Artifact description |
aliases |
string[] |
Optional. List of aliases |
createdAt |
Date |
Creation timestamp |
1.3 - ArtifactVersion
A specific version of a W&B artifact.
const artifactVersion: ArtifactVersion = {
id: "version_xyz789",
version: "v3",
versionIndex: 3,
aliases: ["latest", "production"],
createdAt: new Date("2024-01-15"),
metadata: {
accuracy: 0.95,
model_type: "transformer"
}
};
Property |
Type |
Description |
id |
string |
Version ID |
version |
string |
Version string (e.g., “v3”) |
versionIndex |
number |
Version index number |
aliases |
string[] |
Optional. List of aliases |
createdAt |
Date |
Creation timestamp |
metadata |
object |
Optional. Version metadata |
1.4 - ConfigDict
Configuration dictionary for W&B runs. Stores hyperparameters, settings, and metadata.
// Typical ML configuration:
const config: ConfigDict = {
// Training hyperparameters
learning_rate: 0.001,
batch_size: 32,
epochs: 100,
optimizer: "adam",
// Model architecture
model_name: "resnet50",
num_layers: 50,
dropout_rate: 0.2,
hidden_dims: [512, 256, 128],
// Data settings
dataset: "imagenet",
augmentation: true,
train_split: 0.8,
// System settings
device: "cuda",
num_workers: 4,
seed: 42
};
Value Types
Basic Types
string
: Text values like model names, optimizers, datasets
number
: Numeric values including integers, floats, and scientific notation
boolean
: True/false flags
null
: Null values for optional settings
Complex Types
Array
: Lists of any allowed type (e.g., [512, 256, 128]
)
Object
: Nested configuration groups with string keys
Special W&B Types (automatically handled when logging)
- W&B Tables: Appear as reference objects with table metadata (columns, rows, path)
- W&B Artifacts: Appear as reference objects with version and ID information
// What you see after logging a W&B Table to config:
const config: ConfigDict = {
// ... your normal config ...
// This appears automatically when you log wandb.Table() to config:
"evaluation_results": {
"_type": "table-file",
"ncols": 5,
"nrows": 100,
"path": "media/table/eval_results_2_abc123.table.json"
}
};
// What you see after referencing an artifact in config:
const config: ConfigDict = {
// ... your normal config ...
// This appears when you use an artifact:
"model_artifact": {
"_type": "artifactVersion",
"id": "QXJ0aWZhY3Q6MTIzNDU2",
"version": "v3",
"path": "model-weights:v3"
}
};
Common Patterns
// Nested configuration groups
const config: ConfigDict = {
optimizer: {
type: "adam",
betas: [0.9, 0.999],
weight_decay: 0.0001
},
scheduler: {
type: "cosine",
warmup_steps: 1000
}
};
// Environment and metadata
const config: ConfigDict = {
experiment_name: "baseline_v2",
git_commit: "abc123def",
python_version: "3.9.7",
cuda_version: "11.8"
};
Constraints
- Keys must be strings
- Values must be JSON-serializable
- Keys starting with
_wandb
are reserved
- No functions, undefined, or symbols allowed
1.5 - Entity
Represents a W&B entity (team or individual user).
const entity: Entity = {
id: "entity_abc123",
name: "my-team",
isTeam: true
};
Property |
Type |
Description |
id |
string |
Entity ID |
name |
string |
Entity name |
isTeam |
boolean |
Whether this is a team or individual user |
1.6 - Project
W&B project containing runs, artifacts, and reports.
const project: Project = {
name: "my-awesome-project",
entity: entity,
createdAt: new Date("2023-01-01"),
updatedAt: new Date("2024-01-20")
};
Property |
Type |
Description |
name |
string |
Project name |
entity |
Entity |
Owning entity |
createdAt |
Date |
Creation timestamp |
updatedAt |
Date |
Last update timestamp |
1.7 - Run
A training or evaluation run logged to W&B.
const run: Run = {
id: "run_abc123",
name: "sunny-dawn-42",
state: "finished",
config: {
learning_rate: 0.001,
batch_size: 32,
epochs: 10
},
summaryMetrics: {
loss: 0.023,
accuracy: 0.95,
val_accuracy: 0.93
},
createdAt: new Date("2024-01-15T10:30:00Z"),
updatedAt: new Date("2024-01-15T14:45:00Z")
};
Property |
Type |
Description |
id |
string |
Run ID |
name |
string |
Run name |
state |
string |
Run state (e.g., “running”, “finished”, “failed”) |
config |
ConfigDict |
Optional. Run configuration |
summaryMetrics |
SummaryDict |
Optional. Summary metrics |
createdAt |
Date |
Creation timestamp |
updatedAt |
Date |
Last update timestamp |
1.8 - SummaryDict
Summary dictionary for W&B runs. Stores final metrics, best values, and aggregated results.
// Typical training summary:
const summary: SummaryDict = {
// Final metrics
final_loss: 0.0234,
final_accuracy: 0.9523,
// Best values during training
best_val_loss: 0.0198,
best_val_accuracy: 0.9612,
best_epoch: 87,
// Training statistics
total_train_time: 3600.5, // seconds
total_steps: 50000,
early_stopped: false,
// Test set results
test_accuracy: 0.9487,
test_f1_score: 0.9465
};
Value Types
Basic Types
string
: Text summaries, model paths, status messages
number
: Metrics, scores, counts, durations
boolean
: Binary flags like convergence status
null
: For optional metrics that weren’t computed
Complex Types
Array
: Lists like per-class scores (e.g., [0.92, 0.94, 0.96]
)
Object
: Grouped metrics with string keys
Special W&B Types (automatically handled when logging)
- W&B Histograms: Appear as objects with bins and values arrays
- W&B Tables: Appear as reference objects with table metadata (columns, rows, path)
- W&B Artifacts: Appear as reference objects with version and ID information
// What you see after logging W&B special types to summary:
const summary: SummaryDict = {
// ... your normal metrics ...
// This appears when you log wandb.Histogram():
"weight_distribution": {
"_type": "histogram",
"bins": [0, 0.1, 0.2, 0.3, 0.4, 0.5],
"values": [10, 25, 45, 30, 15, 5]
},
// This appears when you log wandb.Table():
"predictions_table": {
"_type": "table-file",
"ncols": 4,
"nrows": 1000,
"path": "media/table/predictions_3_def456.table.json"
},
// This appears when you reference an artifact:
"best_model": {
"_type": "artifactVersion",
"id": "QXJ0aWZhY3Q6OTg3NjU0",
"version": "v12",
"path": "model-checkpoint:v12"
}
};
Common Patterns
// Grouped metrics by dataset split
const summary: SummaryDict = {
train: {
loss: 0.023,
accuracy: 0.975,
samples_seen: 50000
},
validation: {
loss: 0.045,
accuracy: 0.948,
samples_seen: 10000
},
test: {
loss: 0.041,
accuracy: 0.951,
samples_seen: 10000
}
};
// Multi-class classification results
const summary: SummaryDict = {
accuracy: 0.92,
macro_f1: 0.91,
per_class_precision: [0.95, 0.89, 0.92, 0.90],
per_class_recall: [0.93, 0.91, 0.90, 0.92],
confusion_matrix_logged: true // Actual matrix logged as W&B Table
};
// Model information
const summary: SummaryDict = {
total_parameters: 125_000_000,
trainable_parameters: 124_500_000,
model_size_mb: 476.8,
inference_time_ms: 23.4
};
Constraints
- Keys must be strings
- Values must be JSON-serializable
- Keys starting with
_wandb
are reserved
- Special: Supports NaN for missing/invalid metrics
- No functions, undefined, or symbols allowed
1.9 - Table
W&B Table for structured data logging and visualization.
const table: Table = {
columns: ["epoch", "loss", "accuracy"],
data: [
[1, 0.5, 0.75],
[2, 0.3, 0.85],
[3, 0.2, 0.90]
]
};
Property |
Type |
Description |
columns |
string[] |
Column names |
data |
any[][] |
Table data rows |
2.1 - Artifact Operations
Operations for querying and manipulating W&B artifacts
artifactLink
artifactLink(artifact): string
Gets the URL/link for accessing an artifact in the W&B UI.
Returns a direct link to view the artifact in the W&B web interface,
useful for generating reports or sharing artifact references.
Parameters
Name |
Type |
Description |
artifact |
Artifact |
The artifact to get the link for |
Example: Generate Artifact Link
const link = artifactLink(myArtifact);
console.log(View artifact: ${link});
// Output: https://wandb.ai/entity/project/artifacts/type/name
Example: Create Markdown Links
const artifacts = project.artifacts();
const markdown = artifacts.map(a =>
- ${artifactName(a)}})
).join('\n');
See Also
artifactName
artifactName(artifact): string
Gets the name of an artifact.
Returns the artifact’s unique name within its project.
Parameters
Name |
Type |
Description |
artifact |
Artifact |
The artifact to get the name from |
Example: Display Artifact Names
artifacts.forEach(artifact => {
console.log(Artifact: ${artifactName(artifact)});
});
Example: Filter by Name Pattern
const modelArtifacts = artifacts.filter(a =>
artifactName(a).includes("model")
);
See Also
artifactVersionAlias
artifactVersionAlias(version): string
Gets the alias of an artifact version.
Returns the version alias (e.g., “latest”, “best”, “production”).
Parameters
Example: Find Production Version
const prodVersion = versions.find(v =>
artifactVersionAlias(v) === "production"
);
See Also
artifactVersions - Get all versions
artifactVersionCreatedAt
artifactVersionCreatedAt(version): Date
Gets the creation date of an artifact version.
Returns when a specific version of the artifact was created.
Parameters
Name |
Type |
Description |
version |
ArtifactVersion |
The artifact version to get creation date from |
Example: Sort Versions by Date
const sorted = versions.sort((a, b) =>
artifactVersionCreatedAt(a).getTime() -
artifactVersionCreatedAt(b).getTime()
);
See Also
artifactVersions - Get all versions
artifactVersionDigest
artifactVersionDigest(version): string
Gets the content digest/hash of an artifact version.
Returns the SHA256 digest used to verify artifact integrity.
Parameters
Example: Verify Artifact Integrity
const digest = artifactVersionDigest(version);
const expected = "sha256:abc123...";
if (digest !== expected) {
console.error("Artifact integrity check failed!");
}
See Also
artifactVersions - Get all versions
artifactVersionNumber
artifactVersionNumber(version): number
Gets the version number of an artifact version.
Returns the numeric version identifier.
Parameters
Example: Get Latest Version Number
const versions = artifactVersions(artifact);
const maxVersion = Math.max(...versions.map(v =>
artifactVersionNumber(v)
));
console.log(Latest version: v${maxVersion});
See Also
artifactVersions - Get all versions
artifactVersionSize
artifactVersionSize(version): number
Gets the size of an artifact version in bytes.
Returns the storage size of a specific artifact version.
Parameters
Name |
Type |
Description |
version |
ArtifactVersion |
The artifact version to get size from |
Example: Display Human-Readable Size
const bytes = artifactVersionSize(version);
const mb = (bytes / 1e6).toFixed(2);
console.log(Size: ${mb} MB);
Example: Find Large Artifacts
const largeVersions = versions.filter(v =>
artifactVersionSize(v) > 1e9 // > 1GB
);
See Also
artifactVersions - Get all versions
artifactVersions
artifactVersions(artifact): ArtifactVersion[]
Gets all versions of an artifact.
Returns an array of all version objects for the artifact,
including version numbers, aliases, sizes, and timestamps.
Parameters
Name |
Type |
Description |
artifact |
Artifact |
The artifact to get versions from |
Example: List All Versions
const versions = artifactVersions(myArtifact);
versions.forEach(v => {
console.log(v${v.version}: ${v.alias} (${v.size} bytes));
});
Example: Find Latest Version
const versions = artifactVersions(artifact);
const latest = versions.find(v => v.alias === "latest");
if (latest) {
console.log(Latest is v${latest.version});
}
Example: Calculate Total Storage
const versions = artifactVersions(artifact);
const totalSize = versions.reduce((sum, v) => sum + v.size, 0);
console.log(Total storage: ${(totalSize / 1e9).toFixed(2)} GB);
See Also
2.2 - Run Operations
Operations for querying and manipulating W&B runs
runConfig
runConfig(run): ConfigDict
Extracts the configuration dictionary (ConfigDict
) from a W&B run.
The configuration contains hyperparameters and settings used when the run was initialized.
This is particularly useful for comparing configurations across experiments or filtering
runs based on specific parameter values.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run object to extract configuration from |
Example: Basic Configuration Access
const config = runConfig(myRun);
console.log(config.learning_rate); // 0.001
console.log(config.batch_size); // 32
Example: Filtering Runs by Configuration
// Find all runs with learning rate > 0.01
const highLRRuns = runs.filter(run => {
const config = runConfig(run);
return config.learning_rate > 0.01;
});
Example: Comparing Configurations
const config1 = runConfig(baseline);
const config2 = runConfig(experiment);
const differences = Object.keys(config1).filter(key =>
config1[key] !== config2[key]
);
See Also
- runSummary - For accessing summary metrics
- runHistory - For accessing time-series data
runCreatedAt
Gets the creation timestamp of a W&B run.
Returns when the run was first initialized. Useful for chronological sorting,
filtering by date ranges, or analyzing experiment progression over time.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to get creation time from |
Example: Filter Recent Runs
const oneWeekAgo = new Date();
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
const recentRuns = runs.filter(run =>
runCreatedAt(run) > oneWeekAgo
);
Example: Sort Chronologically
const sortedRuns = runs.sort((a, b) =>
runCreatedAt(a).getTime() - runCreatedAt(b).getTime()
);
Example: Group by Date
const runsByDate = runs.reduce((groups, run) => {
const date = runCreatedAt(run).toDateString();
groups[date] = groups[date] || [];
groups[date].push(run);
return groups;
}, {});
See Also
runHeartbeatAt
runHeartbeatAt(run): Date
Gets the last heartbeat timestamp of a W&B run.
The heartbeat indicates when the run last sent data to W&B. For active runs,
this is continuously updated. For finished runs, it shows the completion time.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to get heartbeat from |
Example: Check if Run is Active
const isActive = (run: Run) => {
const lastHeartbeat = runHeartbeatAt(run);
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
return lastHeartbeat > fiveMinutesAgo;
};
See Also
runJobType
runJobType(run): string | undefined
Gets the job type of a run.
Returns the job type classification (e.g., “train”, “eval”, “sweep”) if set.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to get job type from |
Example: Filter by Job Type
const trainingRuns = runs.filter(run =>
runJobType(run) === "train"
);
const evalRuns = runs.filter(run =>
runJobType(run) === "eval"
);
See Also
Run - Run type definition
runLoggedArtifactVersion
runLoggedArtifactVersion(run, artifactVersionName): ArtifactVersion | undefined
Gets a specific artifact version logged (output) by a run.
Artifacts in W&B are versioned files or directories that track model checkpoints,
datasets, or other outputs. This function retrieves a specific artifact version
that was created/logged during the run’s execution.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run that logged the artifact |
artifactVersionName |
string |
Artifact identifier as “name:alias” (e.g., “model:latest”, “dataset:v2”) |
Example: Get Latest Model
const model = runLoggedArtifactVersion(run, "model:latest");
if (model) {
console.log(Model version: v${model.version});
console.log(Model size: ${model.size} bytes);
console.log(Created: ${model.createdAt});
}
Example: Verify Output Artifacts
const requiredOutputs = ["model:latest", "evaluation:latest"];
const missing = requiredOutputs.filter(name =>
!runLoggedArtifactVersion(run, name)
);
if (missing.length > 0) {
console.warn(Missing outputs: ${missing.join(", ")});
}
See Also
runLoggedArtifactVersions
runLoggedArtifactVersions(run): ArtifactVersion[]
Gets all artifact versions logged (output) by a run.
Returns a complete list of all artifacts created during the run’s execution,
including models, datasets, checkpoints, and other outputs.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to get logged artifacts from |
Example: List All Outputs
const outputs = runLoggedArtifactVersions(run);
outputs.forEach(artifact => {
console.log(Logged: ${artifact.name}:${artifact.alias});
console.log( Version: ${artifact.version});
console.log( Size: ${artifact.size} bytes);
});
Example: Count Output Types
const outputs = runLoggedArtifactVersions(run);
const modelCount = outputs.filter(a => a.name.includes("model")).length;
const dataCount = outputs.filter(a => a.name.includes("data")).length;
console.log(Models: ${modelCount}, Datasets: ${dataCount});
See Also
runName
Gets the name/ID of a run.
Returns the unique run name (ID) assigned by W&B or set by the user.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to get name from |
Example: Display Run Names
runs.forEach(run => {
console.log(Run: ${runName(run)});
});
See Also
Run - Run type definition
runRuntime
Calculates the runtime duration of a W&B run in seconds.
Returns the total execution time from creation to last heartbeat.
For active runs, this represents the current runtime.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to calculate runtime for |
Example: Display Runtime
const runtime = runRuntime(myRun);
const hours = Math.floor(runtime / 3600);
const minutes = Math.floor((runtime % 3600) / 60);
console.log(Runtime: ${hours}h ${minutes}m);
Example: Filter Long-Running Experiments
const longRuns = runs.filter(run =>
runRuntime(run) > 3600 // More than 1 hour
);
See Also
runSummary
runSummary(run): SummaryDict
Retrieves summary metrics (SummaryDict
) from a W&B run.
Summary metrics represent the final or best values logged during a run’s execution,
such as final accuracy, best validation loss, or total training time. These are
scalar values that summarize the run’s overall performance.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to extract summary from |
Example: Accessing Final Metrics
const summary = runSummary(myRun);
console.log(Final accuracy: ${summary.accuracy});
console.log(Best validation loss: ${summary.best_val_loss});
console.log(Training time: ${summary.training_time_seconds});
const bestRun = runs.reduce((best, current) => {
const bestSummary = runSummary(best);
const currentSummary = runSummary(current);
return currentSummary.accuracy > bestSummary.accuracy ? current : best;
});
const goodRuns = runs.filter(run => {
const summary = runSummary(run);
return summary.accuracy > 0.95 && summary.val_loss < 0.1;
});
See Also
- runConfig - For configuration parameters
- runHistory - For time-series metrics
runUsedArtifactVersions
runUsedArtifactVersions(run): ArtifactVersion[]
Gets all artifact versions used (input) by a run.
Returns artifacts that were consumed as inputs during the run’s execution,
such as training datasets, pretrained models, or configuration files.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to get used artifacts from |
const inputs = runUsedArtifactVersions(run);
console.log("Run dependencies:");
inputs.forEach(artifact => {
console.log(- ${artifact.name}:${artifact.version});
});
Example: Verify Dataset Version
const inputs = runUsedArtifactVersions(run);
const dataset = inputs.find(a => a.name === "training-data");
if (dataset && dataset.version !== 3) {
console.warn(Using outdated dataset v${dataset.version});
}
See Also
runUser
Gets the user who created the run.
Returns the W&B user object associated with the run, useful for filtering
by user or analyzing team member contributions.
Parameters
Name |
Type |
Description |
run |
Run |
The W&B run to get user from |
Example: Filter by User
const myRuns = runs.filter(run =>
runUser(run).username === "john_doe"
);
Example: Group Runs by User
const runsByUser = runs.reduce((groups, run) => {
const user = runUser(run).username;
groups[user] = groups[user] || [];
groups[user].push(run);
return groups;
}, {});
See Also
User - User type definition