# ECharts Data Transformation: How to Use registerExternalTransform for Custom Pipelines

> Master ECharts data transformation with registerExternalTransform for custom pipelines. Process raw datasets effectively before rendering. Learn how to build unique data processing steps.

- Repository: [The Apache Software Foundation/echarts](https://github.com/apache/echarts)
- Tags: how-to-guide
- Published: 2026-03-04

---

**ECharts provides a data-transform pipeline that processes raw datasets through configurable steps before rendering, and you can register custom transforms using `registerExternalTransform` with a namespaced type string like `myLib:transformName`.**

Apache ECharts implements a powerful data transformation system that allows developers to manipulate dataset sources before they reach the series rendering stage. The pipeline operates through **`DataTransformOption`** objects and supports both built-in operations and user-defined extensions. Understanding how to leverage **`registerExternalTransform`** enables you to implement domain-specific data manipulations while maintaining type safety and performance.

## Understanding the ECharts Data Transform Architecture

The transformation engine is centralized in [`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts) and revolves around several key abstractions that ensure safe data manipulation.

### Core Interfaces and Types

According to the source code in **[`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts)** (lines 40-57), the pipeline relies on two primary interfaces:

- **`DataTransformOption`** (lines 40-48): Defines a transform step with a `type` string and optional `config` object.
- **`ExternalDataTransform`** (lines 50-57): The interface your custom transform must implement, requiring a `type` property and a `transform` function.

The `ExternalDataTransform` interface specifies that your transform function receives an object containing `upstream`, `upstreamList`, and `config` parameters, and must return either a single result object or an array of results.

### The ExternalSource Safety Wrapper

When transforms execute, ECharts does not expose internal `Source` objects directly. Instead, it wraps upstream data in an **`ExternalSource`** instance ([`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts), lines 92-158). This wrapper provides read-only helper methods including:

- `getRawData()` - Retrieves the raw array-rows.
- `retrieveValue()` - Safe value extraction.
- `cloneRawData()` - Immutable data copying.

This design protects the internal data model while giving transform authors sufficient access to manipulate data.

### Global Registration and Pipeline Execution

The **`registerExternalTransform`** function ([`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts), lines 33-61) maintains a global registry map where transforms are stored under their namespaced keys. When ECharts processes a dataset, **`applyDataTransform`** (lines 63-89) serves as the entry point that:

1. Splits the type string on `:` to identify the namespace.
2. Retrieves the registered `ExternalDataTransform` from the global map.
3. Creates `ExternalSource` wrappers for upstream datasets.
4. Invokes the transform function and normalizes the output through `applySingleDataTransform` (lines 92-140).

## How to Register an External Transform with registerExternalTransform

To add custom transformation logic to your ECharts installation, you must implement the `ExternalDataTransform` interface and register it globally.

### Namespace Requirements and Type Naming

ECharts requires external transforms to use **namespaced type strings** following the pattern `namespace:transformName` (e.g., `myLib:double` or `custom:aggregate`). Built-in transforms reside under the `echarts:` namespace and can be referenced without the prefix (e.g., `filter` instead of `echarts:filter`).

### Implementing the Transform Interface

Your transform object must satisfy the `ExternalDataTransform` interface defined in the source code. The `transform` function receives an object with three properties:

- **`upstream`**: An `ExternalSource` instance for single-source transforms.
- **`upstreamList`**: An array of `ExternalSource` objects for multi-source transforms.
- **`config`**: The configuration object passed from the chart option.

The function must return an object containing at minimum a `data` property (the transformed rows), and optionally a `dimensions` array if the output schema differs from the input.

## Practical Example: Creating a Custom Transform

Here is a complete implementation of a transform that doubles numeric values, demonstrating the patterns found in [`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts):

```typescript
// my-double-transform.ts
import { registerExternalTransform, ExternalDataTransform } from 'echarts/src/data/helper/transform';

const doubleTransform: ExternalDataTransform = {
  type: 'myLib:double',
  transform({ upstream }) {
    // Access raw data through the ExternalSource wrapper
    const data = upstream.getRawData();
    
    const doubled = data.map(row => {
      return row.map(value => 
        typeof value === 'number' ? value * 2 : value
      );
    });
    
    // Return transformed data; dimensions inherited from upstream
    return { data: doubled };
  }
};

// Register globally once during application initialization
registerExternalTransform(doubleTransform);

```

This implementation follows the exact interface requirements specified in the source code, using the read-only `getRawData()` method provided by `ExternalSource` rather than accessing internal data structures directly. The [`src/component/transform.ts`](https://github.com/apache/echarts/blob/main/src/component/transform.ts) file ensures this registration API is available to extension authors.

## Using Custom Transforms in Chart Options

Once registered, external transforms integrate seamlessly into the ECharts option schema alongside built-in transforms.

### Single Transform Application

Apply your registered transform to a dataset using the `transform` property:

```javascript
const option = {
  dataset: {
    source: [
      ['item', 'value'],
      ['A', 10],
      ['B', 20],
      ['C', 30]
    ],
    transform: { type: 'myLib:double' }
  },
  series: [
    { 
      type: 'bar', 
      encode: { x: 'item', y: 'value' } 
    }
  ]
};

```

When rendered, ECharts locates `myLib:double` in the registry via `applyDataTransform`, executes the transformation, and the bar series receives doubled values `[20, 40, 60]`.

### Chaining Multiple Transforms

The `transform` property accepts an array to create processing pipelines:

```javascript
const option = {
  dataset: {
    source: [
      ['category', 'sales', 'profit'],
      ['A', 100, 30],
      ['B', 150, 45],
      ['C', 200, 60]
    ],
    transform: [
      { type: 'filter', config: { dimension: 'profit', lt: 50 } },
      { type: 'myLib:double', config: { dimension: 'sales' } }
    ]
  },
  series: [{ type: 'bar' }]
};

```

ECharts processes transforms sequentially using `applySingleDataTransform` for each step. The pipeline executes in order: first filtering rows where profit is less than 50, then doubling the sales values for the remaining rows.

## Summary

- **ECharts data transformation** operates through a pipeline architecture defined in [`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts) that processes datasets before series rendering.
- **`registerExternalTransform`** stores custom transforms in a global registry using namespaced keys like `myLib:transformName`.
- The **`ExternalSource`** wrapper (lines 92-158) provides safe, read-only access to upstream data through methods like `getRawData()` and `retrieveValue()`.
- Transform implementations must return objects with a `data` property containing the transformed rows, optionally including `dimensions` for schema changes.
- Transforms can be chained in arrays to create complex processing pipelines, mixing built-in transforms (under the `echarts` namespace) with custom external transforms.

## Frequently Asked Questions

### What is the difference between built-in and external transforms in ECharts?

Built-in transforms are registered under the `echarts:` namespace and can be referenced without the prefix (e.g., `filter` or `sort`), while external transforms require explicit namespaced types like `myLib:custom`. Both implement the same `ExternalDataTransform` interface and execute through the same `applyDataTransform` pipeline in [`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts).

### How does the ExternalSource protect internal data models?

The `ExternalSource` class defined in [`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts) (lines 92-158) wraps the internal `Source` objects and exposes only specific read-only methods such as `getRawData()`, `retrieveValue()`, and `cloneRawData()`. This prevents transform functions from corrupting ECharts' internal state while providing sufficient functionality for data manipulation.

### Can I chain multiple external transforms in ECharts?

Yes, the `transform` property in dataset options accepts an array of `DataTransformOption` objects. ECharts processes these sequentially through `applySingleDataTransform`, passing the output of each step as the input to the next. You can mix built-in transforms and custom external transforms in the same pipeline array.

### Where are external transforms stored in the ECharts codebase?

External transforms are stored in a global map maintained by the `registerExternalTransform` function in [`src/data/helper/transform.ts`](https://github.com/apache/echarts/blob/main/src/data/helper/transform.ts) (lines 33-61). The [`src/component/transform.ts`](https://github.com/apache/echarts/blob/main/src/component/transform.ts) file loads the necessary install module to make the registration API available to extension authors, while the core logic resides in the transform helper module.