Toucan AI Docs

Data steps

Reference for every data step used in chart queries: what each one does, its properties, and a JSON example to copy.

Steps are the building blocks of data transformation. They are used in chart queries: each step is a single operation in the query (filtering, aggregating, renaming columns, etc.). Steps run in sequence; the output of one step becomes the input of the next.

The JSON examples in this reference can be copied and adapted for your chart queries. Use the name field to identify the step type and fill in the other properties as described for each step below.

absolutevalue step

This step is meant to compute the absolute value of a given input column.

{
    "name": "absolutevalue",
    "column": "my-column",
    "newColumn": "my-new-column"
}

Example

Input dataset:

CompanyValue
Company 1-33
Company 20
Company 310

Step configuration:

{
  "name": "absolutevalue",
  "column": "Value",
  "newColumn": "My-absolute-value"
}

Output dataset:

CompanyValueMy-absolute-value
Company 1-3333
Company 200
Company 31010

addmissingdates step

Add missing dates as new rows in a dates column. Exhaustive dates will range between the minimum and maximum date found in the dataset (or in each group if a group by logic is applied - see thereafter).

Added rows will be set to null in columns not referenced in the step configuration.

You should make sure to use a group by logic if you want to add missing dates in independent groups of rows (e.g. you may need to add missing rows for every country found in a "COUNTRY" column). And you should ensure that every date is unique in every group of rows at the specified granularity, else you may get inconsistent results. You can specify "group by" columns in the groups parameter.

An addmissingdates step has the following structure:

{
  "name": "addmissingdates",
  "datesColumn": "DATE",
  "datesGranularity": "day",
  "groups": ["COUNTRY"]
}

Example 1: day granularity without groups

Input dataset:

DATEVALUE
"2018-01-01T00:00.000Z"75
"2018-01-02T00:00.000Z"80
"2018-01-03T00:00.000Z"82
"2018-01-04T00:00.000Z"83
"2018-01-05T00:00.000Z"80
"2018-01-07T00:00.000Z"86
"2018-01-08T00:00.000Z"79
"2018-01-09T00:00.000Z"76
"2018-01-10T00:00.000Z"79
"2018-01-11T00:00.000Z"75

Here the day "2018-01-06" is missing.

Step configuration:

{
  "name": "addmissingdates",
  "datesColumn": "DATE",
  "datesGranularity": "day"
}

Output dataset:

DATEVALUE
"2018-01-01T00:00.000Z"75
"2018-01-02T00:00.000Z"80
"2018-01-03T00:00.000Z"82
"2018-01-04T00:00.000Z"83
"2018-01-05T00:00.000Z"80
"2018-01-06T00:00.000Z"
"2018-01-07T00:00.000Z"86
"2018-01-08T00:00.000Z"79
"2018-01-09T00:00.000Z"76
"2018-01-10T00:00.000Z"79
"2018-01-11T00:00.000Z"75

Example 2: day granularity with groups

Input dataset:

COUNTRYDATEVALUE
France"2018-01-01T00:00.000Z"75
France"2018-01-02T00:00.000Z"80
France"2018-01-03T00:00.000Z"82
France"2018-01-04T00:00.000Z"83
France"2018-01-05T00:00.000Z"80
France"2018-01-07T00:00.000Z"86
France"2018-01-08T00:00.000Z"79
France"2018-01-09T00:00.000Z"76
France"2018-01-10T00:00.000Z"79
France"2018-01-11T00:00.000Z"85
USA"2018-01-01T00:00.000Z"69
USA"2018-01-02T00:00.000Z"73
USA"2018-01-03T00:00.000Z"73
USA"2018-01-05T00:00.000Z"75
USA"2018-01-06T00:00.000Z"70
USA"2018-01-07T00:00.000Z"76
USA"2018-01-08T00:00.000Z"73
USA"2018-01-09T00:00.000Z"70
USA"2018-01-10T00:00.000Z"72
USA"2018-01-12T00:00.000Z"78

Here the day "2018-01-06" is missing for "France" rows, and "2018-01-11" and "2018-01-11" are missing for "USA" rows.

Note that "2018-01-12" will not be considered as a missing row for "France" rows, because the latest date found for this group of rows is "2018-01-11" (even though "2018-01-12" is the latest date found for "USA" rows).

Step configuration:

{
  "name": "addmissingdates",
  "datesColumn": "DATE",
  "datesGranularity": "day",
  "groups": ["COUNTRY"]
}

Output dataset:

COUNTRYDATEVALUE
France"2018-01-01T00:00.000Z"75
France"2018-01-02T00:00.000Z"80
France"2018-01-03T00:00.000Z"82
France"2018-01-04T00:00.000Z"83
France"2018-01-05T00:00.000Z"80
France"2018-01-06T00:00.000Z"
France"2018-01-07T00:00.000Z"86
France"2018-01-08T00:00.000Z"79
France"2018-01-09T00:00.000Z"76
France"2018-01-10T00:00.000Z"79
France"2018-01-11T00:00.000Z"85
USA"2018-01-01T00:00.000Z"69
USA"2018-01-02T00:00.000Z"73
USA"2018-01-03T00:00.000Z"73
USA"2018-01-04T00:00.000Z"
USA"2018-01-05T00:00.000Z"75
USA"2018-01-06T00:00.000Z"70
USA"2018-01-07T00:00.000Z"76
USA"2018-01-08T00:00.000Z"73
USA"2018-01-09T00:00.000Z"70
USA"2018-01-10T00:00.000Z"72
USA"2018-01-11T00:00.000Z"
USA"2018-01-12T00:00.000Z"78

Example 3: month granularity

Input dataset:

DATEVALUE
"2019-01-01T00:00.000Z"74
"2019-02-01T00:00.000Z"73
"2019-03-01T00:00.000Z"68
"2019-04-01T00:00.000Z"71
"2019-06-01T00:00.000Z"74
"2019-07-01T00:00.000Z"74
"2019-08-01T00:00.000Z"73
"2019-09-01T00:00.000Z"72
"2019-10-01T00:00.000Z"75
"2019-12-01T00:00.000Z"76

Here "2019-05" and "2019-11" are missing.

Step configuration:

{
  "name": "addmissingdates",
  "datesColumn": "DATE",
  "datesGranularity": "month"
}

Output dataset:

DATEVALUE
"2019-01-01T00:00.000Z"74
"2019-02-01T00:00.000Z"73
"2019-03-01T00:00.000Z"68
"2019-04-01T00:00.000Z"71
"2019-05-01T00:00.000Z"
"2019-06-01T00:00.000Z"74
"2019-07-01T00:00.000Z"74
"2019-08-01T00:00.000Z"73
"2019-09-01T00:00.000Z"72
"2019-10-01T00:00.000Z"75
"2019-11-01T00:00.000Z"
"2019-12-01T00:00.000Z"76

aggregate step

Perform aggregations on one or several columns. Available aggregation functions are sum, average, count, count distinct, min, max, first, last.

An aggregation step has the following structure:

{
   "name": "aggregate",
   "on": ["column1", "column2"],
   "aggregations":  [
    {
      "newcolumns": ["sum_value1", "sum_value2"],
      "aggfunction": "sum",
      "columns": ["value1", "value2"]
    },
    {
      "newcolumns": ["avg_value1"],
      "aggfunction": "avg",
      "columns": ["value1"]
    }
  ],
  "keepOriginalGranularity": false
}

Example 1: keepOriginalGranularity set to false

Input dataset:

LabelGroupValue1Value2
Label 1Group 11310
Label 2Group 1721
Label 3Group 1204
Label 4Group 2117
Label 5Group 2912
Label 6Group 252

Step configuration:

{
  "name": "aggregate",
   "on": ["Group"],
   "aggregations":  [
    {
      "newcolumns": ["Sum-Value1", "Sum-Value2"],
      "aggfunction": "sum",
      "columns": ["Value1", "Value2"]
    },
    {
      "newcolumns": ["Avg-Value1"],
      "aggfunction": "avg",
      "columns": ["Value1"]
    }
  ],
  "keepOriginalGranularity": false
}

Output dataset:

GroupSum-Value1Sum-Value2Avg-Value1
Group 1403513.333333
Group 216315.333333

Example 2: keepOriginalGranularity set to true

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "aggregate",
   "on": ["Group"],
   "aggregations":  [
    {
      "newcolumns": ["Total"],
      "aggfunction": "sum",
      "columns": ["Value"]
    }
  ],
  "keepOriginalGranularity": true
}

Output dataset:

LabelGroupValue
Label 1Group 140
Label 2Group 140
Label 3Group 140
Label 4Group 216
Label 5Group 216
Label 6Group 216

append step

Appends to the current dataset, one or several datasets resulting from other pipelines. WeaverBird allows you to save pipelines referenced by name in the Vuex store of the application. You can then call them by their unique names in this step.

{
  "name": "append",
  "pipelines": ["pipeline1", "pipeline2"]
}

Example

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17

dataset1 (saved in the application Vuex store):

LabelGroupValue
Label 3Group 120
Label 4Group 21

dataset2 (saved in the application Vuex store):

LabelGroupValue
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "append",
  "pipelines": ["dataset1", "dataset2"]
}

Output dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

argmax step

Get row(s) matching the maximum value in a given column, by group if groups is specified.

{
  "name": "argmax",
  "column": "value",
  "groups": ["group1", "group2"]
}

Example 1: without groups

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "argmax",
  "column": "Value"
}

Output dataset:

LabelGroupValue
Label 3Group 120

Example 2: with groups

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "argmax",
  "column": "Value",
  "groups": ["Group"]
}

Output dataset:

LabelGroupValue
Label 3Group 120
Label 5Group 210

argmin step

Get row(s) matching the minimum value in a given column, by group if groups is specified.

{
  "name": "argmin",
  "column": "value",
  "groups": ["group1", "group2"]
}

Example 1: without groups

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "argmin",
  "column": "Value"
}

Output dataset:

LabelGroupValue
Label 4Group 21

Example 2: with groups

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "argmin",
  "column": "Value",
  "groups": ["Groups"]
}

Output dataset:

LabelGroupValue
Label 2Group 17
Label 4Group 21

comparetext step

Compares 2 string columns and returns true if the string values are equal, and false oteherwise. The comparison is case-sensitive (see examples below).

{
  "name": "comparetext",
  "newColumnName": "NEW",
  "strCol1": "TEXT_1",
  "strCol2": "TEXT_2"
}

Example

Input dataset:

TEXT_1TEXT_2
FranceFr
FranceFrance
Francefrance
FranceEngland
FranceUSA

Step configuration:

{
  "name": "split",
  "newColumnName": "RESULT",
  "ctrCol1": "TEXT_1",
  "ctrCol2": "TEXT_2"
}

Output dataset:

TEXT_1TEXT_2RESULT
FranceFrfalse
FranceFrancetrue
Francefrancefalse
FranceEnglandfalse
FranceUSAfalse

concatenate step

This step allows to concatenate several columns using a separator.

{
  "name": "concatenate",
  "columns": ["Company", "Group"],
  "separator": " - ",
  "newColumnName": "Label"
}

Example

Input dataset:

CompanyGroupValue
Company 1Group 113
Company 2Group 17
Company 3Group 120
Company 4Group 21
Company 5Group 210
Company 6Group 25

Step configuration:

{
  "name": "concatenate",
  "columns": ["Company", "Group"],
  "separator": " - ",
  "newColumnName": "Label"
}

Output dataset:

CompanyGroupValueLabel
Company 1Group 113Company 1 - Group 1
Company 2Group 17Company 2 - Group 1
Company 3Group 120Company 3 - Group 1
Company 4Group 21Company 4 - Group 2
Company 5Group 210Company 5 - Group 2
Company 6Group 25Company 6 - Group 2

convert step

This step allows to convert columns data types.

{
  "name": "convert",
  "columns": ["col1", "col2"],
  "dataType": "integer"

}

In a effort to harmonize as much as possible the conversion behaviors, for some cases, the Sql translator implements casting otherwise than the CAST AS method.

Precisely, when casting float to integer, the default behaviour rounds the result, other languages truncate it. That's why the use of TRUNCATE was implemented when converting float to int. The same implementation was done when converting strings to int (for date represented as string). As for the conversion of date to int, we handled it by assuming the dataset's timestamp is in TIMESTAMP_NTZ format.

Example

Input dataset:

CompanyValue
Company 1'13'
Company 2'7'
Company 3'20'
Company 4'1'
Company 5'10'
Company 6'5'

Step configuration:

{
  "name": "convert",
  "columns": ["Value"],
  "dataType": "integer"
}

Output dataset:

CompanyValue
Company 113
Company 27
Company 320
Company 41
Company 510
Company 65

cumsum step

This step allows to compute the cumulated sum of value columns based on a reference column (usually dates) to be sorted by ascending order for the needs of the computation. The computation can be scoped by group if needed.

The toCumSum parameter takes as input a list of 2-elements lists in the form ['valueColumn', 'newColumn'].

{
  "name": "cumsum",
  "toCumSum": [["myValues", "myCumsum"]],
  "referenceColumn": "myDates",
  "groupby": ["foo", "bar"]
}

Example 1: Basic usage

Input dataset:

DATEVALUE
2019-012
2019-025
2019-033
2019-048
2019-059
2019-066

Step configuration:

{
  "name": "cumsum",
  "toCumSum": [["VALUE", ""]],
  "referenceColumn": "DATE"
}

Output dataset:

DATEVALUEVALUE_CUMSUM
2019-0122
2019-0257
2019-03310
2019-04818
2019-05927
2019-06 6633

Example 2: With more advanced options

Input dataset:

COUNTRYDATEVALUE
France2019-012
France2019-025
France2019-033
France2019-048
France2019-059
France2019-06 66
USA2019-0110
USA2019-026
USA2019-036
USA2019-044
USA2019-058
USA2019-06 67

Step configuration:

{
  "name": "cumsum",
  "toCumSum": [["VALUE", "MY_CUMSUM"]],
  "referenceColumn": "DATE",
  "groupby": ["COUNTRY"]
}

Output dataset:

COUNTRYDATEVALUEMY_CUMSUM
France2019-0122
France2019-0257
France2019-03310
France2019-04818
France2019-05927
France2019-06 6633
USA2019-011010
USA2019-02616
USA2019-03622
USA2019-04426
USA2019-05834
USA2019-06 6741

dateextract step

Extract date information (eg. day, week, year etc.). The following information can be extracted:

  • year: extract 'year' from date,
  • month: extract 'month' from date,
  • day: extract 'day of month' from date,
  • week': extract 'week number' (ranging from 0 to 53) from date,
  • quarter: extract 'quarter number' from date (1 for Jan-Feb-Mar)
  • dayOfWeek: extract 'day of week' (ranging from 1 for Sunday to 7 for Staurday) from date,
  • dayOfYear: extract 'day of year' from date,
  • isoYear: extract 'year number' in ISO 8601 format (ranging from 1 to 53) from date.
  • isoWeek: extract 'week number' in ISO 8601 format (ranging from 1 to 53) from date.
  • isoDayOfWeek: extract 'day of week' in ISO 8601 format (ranging from 1 for Monday to 7 for Sunday) from date,
  • firstDayOfYear: calendar date corresponding to the first day (1st of January) of the year ,
  • firstDayOfMonth: calendar date corresponding to the first day of the month,
  • firstDayOfWeek: calendar date corresponding to the first day of the week,
  • firstDayOfQuarter: calendar date corresponding to the first day of the quarter,
  • firstDayOfIsoWeek: calendar date corresponding to the first day of the week in ISO 8601 format,
  • currentDay: calendar date of the target date,
  • previousDay: calendar date one day before the target date,
  • firstDayOfPreviousYear: calendar date corresponding to the first day (1st of January) of the previous year,
  • firstDayOfPreviousMonth: calendar date corresponding to the first day of the previous month,
  • firstDayOfPreviousWeek: calendar date corresponding to the first day of the previous week,
  • firstDayOfPreviousQuarter: calendar date corresponding to the first day of the previous quarter,
  • firstDayOfPreviousISOWeek: calendar date corresponding to the first day of the previous ISO week,
  • previousYear: extract previous 'year number' from date
  • previousMonth: extract previous 'month number' from date
  • previousWeek: extract previous 'week number' from date
  • previousQuarter: extract previous 'quarter number' from date
  • previousISOWeek: extract previous 'week number' in ISO 8601 format (ranging from 1 for Monday to 7 for Sunday) from date
  • hour: extract 'hour' from date,
  • minutes: extract 'minutes' from date,
  • seconds: extract 'seconds' from date,
  • milliseconds: extract 'milliseconds' from date,

Here's an example of such a step:

{
  "name": "dateextract",
  "column": "date",
  "dateInfo": ["year", "month", "day"],
  "newColumns": ["date_year", "date_month", "date_day"]
}

Example

Input dataset:

Date
2019-10-30T00:00.000Z
2019-10-15T00:00.000Z
2019-10-01T00:00.000Z
2019-09-30T00:00.000Z
2019-09-15T00:00.000Z
2019-09-01T00:00.000Z

Step configuration:

{
  "name": "dateextract",
  "column": "Date",
  "dateInfo": ["year", "month", "day"],
  "newColumns": ["Date_year", "Date_month", "Date_day"]
}

Output dataset:

DateDate_yearDate_monthDate_day
2019-10-30T00:00.000Z20191030
2019-10-15T00:00.000Z20191015
2019-10-01T00:00.000Z2019101
2019-09-30T00:00.000Z20201030
2019-09-15T00:00.000Z20201015
2019-09-01T00:00.000Z2020101

datetimefromparts step

Assemble a datetime column from date/time parts stored in separate columns. Each part can come from a column or from a literal integer value shared by every row. Non-integer column values (text, floats) are cast automatically before parsing.

Use this step when your source data stores year, month, and day in separate fields — for example after an export from a legacy database.

{
  "name": "datetimefromparts",
  "newColumnName": "order_date",
  "year": {
    "column": "yr"
  },
  "month": {
    "column": "mo"
  },
  "day": {
    "column": "dy"
  }
}

Parameters

ParameterRequiredDescription
newColumnNameyesName of the new datetime column
yearyesYear part — from a column or a literal (see below)
yearFormatnoFormat of the year column: %Y (4 digits, default) or %y (2 digits). Ignored when year is a literal
monthnoMonth part. Defaults to January when omitted
monthFormatnoFormat of the month column: %m (number, default), %B (full name, e.g. March), %b or %h (abbreviated, e.g. Mar). Ignored when month is a literal
daynoDay of the month. Defaults to the 1st when omitted
hournoHour. Defaults to 0 when omitted
minutenoMinutes. Defaults to 0 when omitted
secondnoSeconds. Defaults to 0 when omitted

Date part source

Each date/time part (year, month, day, hour, minute, second) is a date part source — either:

  • from a column: { "column": "yr" }
  • or a literal integer applied to every row: { "value": 2024 }

Example 1: rebuild a date from numeric columns

Input dataset:

yrmodyamount
2024315120
202412185
20237442

Step configuration:

{
  "name": "datetimefromparts",
  "newColumnName": "order_date",
  "year": {
    "column": "yr"
  },
  "month": {
    "column": "mo"
  },
  "day": {
    "column": "dy"
  }
}

Output dataset:

yrmodyamountorder_date
20243151202024-03-15T00:00.000Z
2024121852024-12-01T00:00.000Z
202374422023-07-04T00:00.000Z

Example 2: fixed year and month names

When the month is stored as text (e.g. March, Jan), use monthFormat to tell the step how to parse it. A literal year applies the same year to every row.

Input dataset:

month_namesales
March1200
January980
December1450

Step configuration:

{
  "name": "datetimefromparts",
  "newColumnName": "period",
  "year": {
    "value": 2024
  },
  "month": {
    "column": "month_name"
  },
  "monthFormat": "%B"
}

Output dataset:

month_namesalesperiod
March12002024-03-01T00:00.000Z
January9802024-01-01T00:00.000Z
December14502024-12-01T00:00.000Z

dategranularity step

Extract date information (eg. day, week, year etc.) in a column intended for aggregation. The following granularities are supported:

  • year: calendar date corresponding to the first day (1st of January) of the year
  • quarter: calendar date corresponding to the first day of the quarter
  • month: calendar date corresponding to the first day of the month
  • week: calendar date corresponding to the first day of the week (sunday)
  • isoWeek: calendar date corresponding to the first day of the week (monday)
  • day: calendar date corresponding to the first hour of the day

Here's an example of such a step:

{
  "name": "dategranularity",
  "column": "date",
  "granularity": "year",
  "newColumn": "do_the_aggregate_on_this"
}

Example

Input dataset:

Date
2019-10-30T00:00.000Z
2019-10-15T00:00.000Z
2019-10-01T00:00.000Z
2019-09-30T05:11.000Z
2019-09-15T00:00.000Z
2019-09-01T00:00.000Z

Step configuration:

{
  "name": "dategranularity",
  "column": "Date",
  "granularity": "month"
}

Output dataset:

Date
2019-10-01T00:00.000Z
2019-10-01T00:00.000Z
2019-10-01T00:00.000Z
2019-09-01T00:00.000Z
2019-09-01T00:00.000Z
2019-09-01T00:00.000Z

Sub-day granularities

When the source column contains timestamps (not just dates), you can bucket at finer intervals:

  • twelveHours: start of the 12-hour period
  • sixHours: start of the 6-hour period
  • threeHours: start of the 3-hour period
  • twoHours: start of the 2-hour period
  • hour: start of the hour
  • halfHour: start of the 30-minute period
  • quarterHour: start of the 15-minute period
  • fiveMinutes: start of the 5-minute period
  • minute: start of the minute

Each value floors the timestamp to the start of its bucket (useful before an aggregate step).

{
    "name": "dategranularity",
    "column": "event_at",
    "granularity": "hour"
}

delete step

Delete a column.

{
    "name": "delete",
    "columns": ["my-column", "some-other-column"]
}

Example

Input dataset:

CompanyGroupValueLabel
Company 1Group 113Company 1 - Group 1
Company 2Group 17Company 2 - Group 1
Company 3Group 120Company 3 - Group 1
Company 4Group 21Company 4 - Group 2
Company 5Group 210Company 5 - Group 2
Company 6Group 25Company 6 - Group 2

Step configuration:

{
  "name": "delete",
  "columns": ["Company", "Group"]
}

Output dataset:

ValueLabel
13Company 1 - Group 1
7Company 2 - Group 1
20Company 3 - Group 1
1Company 4 - Group 2
10Company 5 - Group 2
5Company 6 - Group 2

duplicate step

This step is meant to duplicate a column.

{
    "name": "duplicate",
    "column": "my-column",
    "newColumnName": "my-duplicate"
}

Example

Input dataset:

CompanyValue
Company 113
Company 20
Company 320

Step configuration:

{
  "name": "duplicate",
  "column": "Company",
  "newColumnName": "Company-copy"
}

Output dataset:

CompanyValueCompany-copy
Company 113Company 1
Company 20Company 2
Company 320Company 3

duration step

Compute the duration (in days, hours, minutes or seconds) between 2 dates in a new column.

{
  "name": "duration",
  "newColumnName": "DURATION",
  "startDateColumn": "START_DATE",
  "endDateColumn": "END_DATE",
  "durationIn": "days"
}

Example 1: duration in days

Input dataset:

START_DATEEND_DATE
"2020-01-01T00:00.000Z""2020-01-31T00:00.000Z"
"2020-01-01T00:00.000Z""2020-12-31T00:00.000Z"

Step configuration:

{
  "name": "duration",
  "newColumnName": "DURATION",
  "startDateColumn": "START_DATE",
  "endDateColumn": "END_DATE",
  "durationIn": "days"
}

Output dataset:

START_HOUREND_HOURDURATION
"2020-01-01T00:00.000Z""2020-01-31T00:00.000Z"30
"2020-01-01T00:00.000Z""2020-12-31T00:00.000Z"365

Example 2: duration in minutes

Input dataset:

START_HOUREND_HOUR
"2020-01-01T14:00.000Z""2020-01-31T15:00.000Z"
"2020-01-01T15:00.000Z""2020-12-31T20:00.000Z"

Step configuration:

{
  "name": "duration",
  "newColumnName": "DURATION",
  "startDateColumn": "START_HOUR",
  "endDateColumn": "END_HOUR",
  "durationIn": "minutes"
}

Output dataset:

START_HOUREND_HOURDURATION
"2020-01-01T14:00.000Z""2020-01-31T15:00.000Z"60
"2020-01-01T15:00.000Z""2020-12-31T20:00.000Z"300

evolution step

Use this step if you need to compute the row-by-row evolution of a value column, based on a date column. It will output 2 columns: one for the evolution in absolute value, the other for the evolution in percentage.

You must be careful that the computation is scoped so that there are no dates duplicates (so that any date finds no more than one previous date). That means that you may need to specify "group by" columns to make any date unique inside each group. You should specify those columns in the indexColumns parameter.

{
  "name": "evolution",
  "dateCol": "DATE",
  "valueCol": "VALUE",
  "evolutionType": "vsLastYear",
  "evolutionFormat": "abs",
  "indexColumns": ["COUNTRY"],
  "newColumn": "MY_EVOL"
}

Example 1: Basic configuration - evolution in absolute value

Input dataset:

DATEVALUE
2019-0679
2019-0781
2019-0877
2019-0975
2019-1178
2019-1288

Step configuration:

{
  "name": "evolution",
  "dateCol": "DATE",
  "valueCol": "VALUE",
  "evolutionType": "vsLastMonth",
  "evolutionFormat": "abs",
  "indexColumns": []
}

Output dataset:

DATEVALUEVALUE_EVOL_ABS
2019-0679
2019-07812
2019-0877-4
2019-0975-2
2019-1178
2019-128810

Example 2: Basic configuration - evolution in percentage

Input dataset:

DATEVALUE
2019-0679
2019-0781
2019-0877
2019-0975
2019-1178
2019-1288

Step configuration:

{
  "name": "evolution",
  "dateCol": "DATE",
  "valueCol": "VALUE",
  "evolutionType": "vsLastMonth",
  "evolutionFormat": "pct",
  "indexColumns": []
}

Output dataset:

DATEVALUEVALUE_EVOL_PCT
2019-0679
2019-07810.02531645569620253
2019-0877-0.04938271604938271
2019-0975-0.025974025974025976
2019-1178
2019-12880.1282051282051282

Example 3: Error on duplicate dates

If 'COUNTRY' is not specified as indexColumn, the computation will not be scoped by country. Then there are duplicate dates in the "DATE" columns which is prohibited and will lead to an error.

Input dataset:

DATECOUNTRYVALUE
2014-12France79
2015-12France81
2016-12France77
2017-12France75
2014-12USA74
2015-12USA74
2016-12USA73
2017-12USA72

Step configuration:

{
  "name": "evolution",
  "dateCol": "DATE",
  "valueCol": "VALUE",
  "evolutionType": "vsLastYear",
  "evolutionFormat": "abs",
  "indexColumns": []
}

Output dataset:

DATECOUNTRYVALUEMY_EVOL
2014-12France79
2015-12France81Error ...
2016-12France77Error ...
2017-12France75Error ...
2014-12USA74
2015-12USA74Error ...
2016-12USA73Error ...
2017-12USA72Error ...

Example 4: Complete configuration with index columns

Input dataset:

DATECOUNTRYVALUE
2014-12France79
2015-12France81
2016-12France77
2017-12France75
2019-12France78
2020-12France88
2014-12USA74
2015-12USA74
2016-12USA73
2017-12USA72
2018-11USA75
2020-12USA76

Step configuration:

{
  "name": "evolution",
  "dateCol": "DATE",
  "valueCol": "VALUE",
  "evolutionType": "vsLastYear",
  "evolutionFormat": "abs",
  "indexColumns": ["COUNTRY"],
  "newColumn": "MY_EVOL"
}

Output dataset:

DATECOUNTRYVALUEMY_EVOL
2014-12France79
2015-12France812
2016-12France77-4
2017-12France75-2
2019-12France78
2020-12France8810
2014-12USA74
2015-12USA740
2016-12USA73-1
2017-12USA72-1
2018-11USA753
2020-12USA76

fillna step

Replace null values by a given value in specified columns.

{
    "name": "fillna",
    "columns": ["foo", "bar"],
    "value": 0
}

Example

Input dataset:

CompanyGroupValueKPI
Company 1Group 113
Company 2Group 112
Company 3Group 12040
Company 4Group 21
Company 5Group 238
Company 6Group 254

Step configuration:

{
  "name": "fillna",
  "columns": ["Value", "KPI"],
  "value": 0
}

Output dataset:

CompanyGroupValueKPI
Company 1Group 1130
Company 2Group 1012
Company 3Group 12040
Company 4Group 210
Company 5Group 2038
Company 6Group 254

filter step

Filter out lines that don't match a filter definition.

{
    "name": "filter",
    "condition": {
      "column": "my-column",
      "value": 42,
      "operator": "ne"
    }
}

operator is optional, and defaults to eq. Allowed operators are eq, ne, gt, ge, lt, le, in, nin, matches, notmatches isnull or notnull.

value can be an arbitrary value depending on the selected operator (e.g a list when used with the in operator, or null when used with the isnull operator).

matches and notmatches operators are used to test value against a regular expression.

Conditions can be grouped and nested with logical operators and and or.

{
    "name": "filter",
    "condition": {
      "and": [
        {
          "column": "my-column",
          "value": 42,
          "operator": "gte"
        },
        {
          "column": "my-column",
          "value": 118,
          "operator": "lte"
        },
        {
          "or": [
            {
              "column": "my-other-column",
              "value": "blue",
              "operator": "eq"
            },
            {
              "column": "my-other-column",
              "value": "red",
              "operator": "eq"
            }
          ]
        }
      ]
    }
}

Relative dates

Date values can be relative to the moment to the moment when the query is executed. This is expressed by using a RelativeDate object instead of the value, of the form:

{
  "quantity": Number,
  "duration": "year" | "quarter" | "month" | "week" | "day"
}

formula step

Add a computation based on a formula. Usually column names do not need to be escaped, unless they include whitespaces, in which case you'll need to use brackets '[]' (e.g. [myColumn]). Any string escaped with quotes (', ", ''', """) will be considered a string literal.

{
  {
    "name": "formula",
    "newColumn": "result",
    "formula": "(Value1 + Value2) / Value3 - Value4 * 2"
  }
}

Supported operators

The following operators are supported by the formula step (note that a value can be a column name or a literal, such as 42 or foo).

  • +: Does an addition of two numeric values. See the concatenate step to append strings
  • -: Does an substraction of two numeric values. See the replace step to remove a part of a string
  • *: Multiplies two numeric values.
  • /: Divides a numeric value by another. Divisions by zero will return null.
  • %: Returns the rest of an integer division. Divisions by zero will return null.

Example 1: Basic usage

Input dataset:

LabelValue1Value2Value3Value4
Label 110231
Label 211373
Label 352052

Step configuration:

{
  "name": "formula",
  "newColumn": "Result",
  "formula": "(Value1 + Value2) / Value3 - Value4 * 2"
}

Output dataset:

LabelValue1Value2Value3Value4Result
Label 1102312
Label 211373-4
Label 3520521

Example 2: Column name with whitespaces

Input dataset:

LabelValue1Value2Value3Value 4
Label 110231
Label 211373
Label 352052

Step configuration:

{
  "name": "formula",
  "newColumn": "Result",
  "formula": "(Value1 + Value2) / Value3 - [Value 4] * 2"
}

Output dataset:

LabelValue1Value2Value3Value 4Result
Label 1102312
Label 211373-4
Label 3520521

ifthenelse step

Creates a new column, which values will depend on a condition expressed on existing columns.

The condition is expressed in the if parameter with a condition object, which is the same object expected by the condition parameter of the filter step). Conditions can be grouped and nested with logical operators and and or.

The then parameter only supports a string, that will be interpreted as a formula (cf. formula step). If you want it to be interpreted striclty as a string and not a formula, you must escape the string with quotes (e.g. '"this is a text"').

if...then...else blocks can be nested as the else parameter supports either a string that will be interpreted as a formula (cf. formula step), or a nested if if...then...else object.

{
  "name": "ifthenelse",
  "newColumn": "",
  "if": { "column": "", "value": "", "operator": "eq" },
  "then": "",
  "else": ""
}

Example

Input dataset:

Labelnumber
Label 1-2
Label 22
Label 30

Step configuration:

{
    "name": "ifthenelse",
    "newColumn": "result",
    "if": { "column": "number", "value": 0, "operator": "eq" },
    "then": ""zero""
    "else": {
      "if": { "column": "rel", "value": 0, "operator": "lt" },
      "then": "number * -1",
      "else": "number"
    }
}

Output dataset:

Labelnumberresult
Label 1-22
Label 255
Label 30zero

join step

Joins a dataset to the current dataset, i.e. brings columns from the former into the latter, and matches rows based on columns correspondance. It is similar to a JOIN clause in SQL, or to a VLOOKUP in excel. The joined dataset is the result from the query of the right_pipeline.

The join type can be:

  • 'left': will keep every row of the current dataset and fill unmatched rows with null values,
  • 'inner': will only keep rows that match rows of the joined dataset.

In the on parameter, you must specify 1 or more column couple(s) that will be compared to determine rows correspondance between the 2 datasets. The first element of a couple is for the current dataset column, and the second for the corresponding column in the right dataset to be joined. If you specify more than 1 couple, the matching rows will be those that find a correspondance between the 2 datasets for every column couple specified (logical 'AND').

Weaverbird allows you to save pipelines referenced by name in the Vuex store of the application. You can then call them by their unique names in this step.

{
  "name": "join",
  "right": {
     "source": {
        "table": {
          "schema": "other_schema",
          "name": "other_table", 
          "columns": ["first_name", "age", "department"]
        }
     },
     "steps": []
  },
  "type": "left",
  "on": [
    ["currentDatasetColumn1", "rightDatasetColumn1"],
    ["currentDatasetColumn2", "rightDatasetColumn2"]
  ]
}

Example 1: Left join with one column couple as on parameter

Input dataset:

LabelValue
Label 113
Label 27
Label 320
Label 41
Label 51
Label 61

rightDataset (saved in the application Vuex store):

LabelGroup
Label 1Group 1
Label 2Group 1
Label 3Group 2
Label 4Group 2

Step configuration:

{
  "name": "join",
  "right": {
     "source": {
        "table": {
          "schema": "other_schema",
          "name": "other_table",     
          "columns": ["first_name", "age", "department"],
        }
     },
     "steps": []
  },
  "type": "left",
  "on": [["Label", "Label"]];
}

Output dataset:

LabelValueGroup
Label 113Group 1
Label 27Group 1
Label 320Group 2
Label 41Group 2
Label 51
Label 61

Example 2: inner join with different column names in the on parameter

Input dataset:

LabelValue
Label 113
Label 27
Label 320
Label 41
Label 51
Label 61

rightDataset (saved in the application Vuex store):

LabelRightGroup
Label 1Group 1
Label 2Group 1
Label 3Group 2
Label 4Group 2

Step configuration:

{
  "name": "join",
  "right": {
     "source": {
        "table": {
          "schema": "other_schema",
          "name": "other_table",     
          "columns": ["first_name", "age", "department"]
        }
     },
     "steps": []
  },
  "type": "inner",
  "on": [["Label", "LabelRight"]];
}

Output dataset:

LabelValueLabelRightGroup
Label 113Label 1Group 1
Label 27Label 2Group 1
Label 320Label 3Group 2
Label 41Label 4Group 2

fromdate step

Converts a date column into a string column based on a specified format.

{
    "name": "fromdate",
    "column": "myDateColumn",
    "format": "%Y-%m-%d"

}

Example

Input dataset:

CompanyDateValue
Company 12019-10-06T00:00.000Z13
Company 12019-10-07T00:00.000Z7
Company 12019-10-08T00:00.000Z20
Company 22019-10-06T00:00.000Z1
Company 22019-10-07T00:00.000Z10
Company 22019-10-08T00:00.000Z5

Step configuration:

{
  "name": "fromdate",
  "column": "Date",
  "format": "%d/%m/%Y"
}

Output dataset:

CompanyDateValue
Company 106/10/201913
Company 107/10/20197
Company 108/10/201920
Company 206/10/20191
Company 207/10/201910
Company 208/10/20195

lowercase step

Converts a string column to lowercase.

{
  "name": "lowercase",
  "column": "foo"
}

Example:

Input dataset:

LabelGroupValue
LABEL 1Group 113
LABEL 2Group 17
LABEL 3Group 120

Step configuration:

{
  "name": "lowercase",
  "column": "Label"
}

Output dataset:

LabelGroupValue
label 1Group 113
label 2Group 17
label 3Group 120

movingaverage step

Compute the moving average based on a value column, a reference column to sort (usually a date column) and a moving window (in number of rows i.e. data points). If needed, the computation can be performed by group of rows. The computation result is added in a new column.

{
  "name": "movingaverage",
  "valueColumn": "value",
  "columnToSort": "dates",
  "movingWindow": 12,
  "groups": ["foo", "bar"],
  "newColumnName": "myNewColumn"
}

Example 1: Basic usage

Input dataset:

DATEVALUE
2018-01-0175
2018-01-0280
2018-01-0382
2018-01-0483
2018-01-0580
2018-01-0686
2018-01-0779
2018-01-0876

Step configuration:

{
  "name": "movingaverage",
  "valueColumn": "VALUE",
  "columnToSort": "DATE",
  "movingWindow": 2
}

Output dataset:

DATEVALUEVALUE_MOVING_AVG
2018-01-0175null
2018-01-028077.5
2018-01-038281
2018-01-048382.5
2018-01-058081.5
2018-01-068683
2018-01-077982.5
2018-01-087677.5

Example 2: with groups and custom newColumnName

Input dataset:

COUNTRYDATEVALUE
France2018-01-0175
France2018-01-0280
France2018-01-0382
France2018-01-0483
France2018-01-0580
France2018-01-0686
USA2018-01-0169
USA2018-01-0273
USA2018-01-0373
USA2018-01-0475
USA2018-01-0570
USA2018-01-0676

Step configuration:

{
  "name": "movingaverage",
  "valueColumn": "VALUE",
  "columnToSort": "DATE",
  "movingWindow": 2,
  "groups": ["COUNTRY"],
  "newColumnName": "ROLLING_AVERAGE"
}

Output dataset:

COUNTRYDATEVALUEROLLING_AVERAGE
France2018-01-0175null
France2018-01-0280null
France2018-01-038279
France2018-01-048381.7
France2018-01-058081.7
France2018-01-068683
USA2018-01-0169null
USA2018-01-0273null
USA2018-01-037371.7
USA2018-01-047573.7
USA2018-01-057072.7
USA2018-01-067673.7

percentage step

Compute the percentage of total, i.e. for every row the value in column divided by the total as the sum of every values in column. The computation can be performed by group if specified. The result is written in a new column.

{
  "name": "percentage",
  "column": "bar",
  "group": ["foo"],
  "newColumnName": "myNewColumn"
}

Example:

Input dataset:

LabelGroupValue
Label 1Group 15
Label 2Group 110
Label 3Group 115
Label 4Group 22
Label 5Group 27
Label 6Group 25

Step configuration:

{
  "name": "percentage",
  "newColumn": "Percentage_of_total",
  "column": "Value",
  "group": ["Group"],
  "newColumn": "Percentage"
}

Output dataset:

LabelGroupValuePercentage
Label 1Group 150.167
Label 2Group 1100.333
Label 3Group 1150.5
Label 4Group 220.143
Label 5Group 270.5
Label 6Group 250.357

pivot step

Pivot rows into columns around a given index (expressed as a combination of column(s)). Values to be used as new column names are found in the column column_to_pivot. Values to populate new columns are found in the column value_column. The function used to aggregate data (when several rows are found by index group) must be among sum, avg, count, min or max.

{
 "name": "pivot",
 "index": ["column_1", "column_2"],
 "columnToPivot": "column_3",
 "valueColumn": "column_4",
 "aggFunction": "sum"
}

Example:

Input dataset:

LabelCountryValue
Label 1Country113
Label 2Country17
Label 3Country120
Label 1Country21
Label 2Country210
Label 3Country25
label 3Country21

Step configuration:

{
 "name": "pivot",
 "index": ["Label"],
 "columnToPivot": "Country",
 "valueColumn": "Value",
 "aggFunction": "sum"
}

Output dataset:

LabelCountry1Country2
Label 1131
Label 2710
Label 3206

statistics step

Compute statistics of a column.,

{
    "name": "statistics",
    "column": "Value",
    "groupby": [],
    "statistics": ["average", "count"],
    "quantiles": [{"label": "median", "nth": 1, "order": 2}]
}

Example:

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
    "name": "statistics",
    "column": "Value",
    "groupby": [],
    "statistics": ["average", "count"],
    "quantiles": [{"label": "median", "nth": 1, "order": 2}]
}

Output dataset:

averagecountmedian
9.3333368.5

rank step

This step allows to compute a rank column based on a value column that can be sorted in ascending or descending order. The ranking can be computed by group.

There are 2 ranking methods available, that you will understand easily through those examples:

  • standard: input = [10, 20, 20, 20, 25, 25, 30] => ranking = [1, 2, 2, 2, 5, 5, 7]
  • dense: input = [10, 20, 20, 20, 25, 25, 30] => ranking = [1, 2, 2, 2, 3, 3, 4]

(The dense method is basically the same as the standard method, but rank always increases by 1 at most).

{
  "name": "rank",
  "valueCol": "VALUE",
  "order": "desc",
  "method": "standard",
  "groupby": ["foo", "bar"],
  "newColumnName": "columnA"
}

Example 1: Basic usage

Input dataset:

COUNTRYVALUE
FRANCE15
FRANCE5
FRANCE10
FRANCE20
FRANCE10
FRANCE15
USA20
USA30
USA20
USA25
USA15
USA20

Step configuration:

{
  "name": "rank",
  "valueCol": "VALUE",
  "order": "desc",
  "method": "standard"
}

Output dataset:

COUNTRYVALUEVALUE_RANK
USA301
USA252
FRANCE203
USA203
USA203
USA203
FRANCE157
FRANCE157
USA157
FRANCE1010
FRANCE1010
FRANCE512

Example 2: With more options

Input dataset:

COUNTRYVALUE
FRANCE15
FRANCE5
FRANCE10
FRANCE20
FRANCE10
FRANCE15
USA20
USA30
USA20
USA25
USA15
USA20

Step configuration:

{
  "name": "rank",
  "valueCol": "VALUE",
  "order": "asc",
  "method": "dense",
  "groupby": ["COUNTRY"],
  "newColumnName": "MY_RANK"
}

Output dataset:

COUNTRYVALUEMY_RANK
FRANCE51
FRANCE102
FRANCE102
FRANCE153
FRANCE153
FRANCE204
USA151
USA202
USA202
USA202
USA253
USA304

rename step

Rename one or several columns. The toRename parameter takes as input a list of 2-elements lists in the form ['oldColumnName', 'newColumnName'].

{
    "name": "rename",
    "toRename": [
      ["oldCol1", "newCol1"]
      ["oldCol2", "newCol2"]
    ]
}

Example:

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "rename",
  "toRename": [["Label", "Company"]]
}

Output dataset:

CompanyGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

replace step

Replace one or several values in a column.

A replace step has the following strucure:

{
   "name": "replace",
   "searchColumn": "column_1",
   "toReplace": [
     ["foo", "bar"],
     [42, 0]
   ]
}

Example

Input dataset:

COMPANYCOUNTRY
Company 1Fr
Company 2UK

Step configuration:

{
   "name": "replace",
   "searchColumn": "COUNTRY",
   "toReplace": [
     ["Fr", "France"],
     ["UK", "United Kingdom"]
   ]
}

Output dataset:

COMPANYCOUNTRY
Company 1France
Company 2United Kingdom

replacetext step

Replace a substring in a column.

A replace-text step has the following structure:

{
   "name": "replacetext",
   "searchColumn": "column_1",
   "oldStr": "foo",
   "newStr": "bar"
}

Example

Input dataset:

COMPANYCOUNTRY
Company 1Fr is boring
Company 2UK

Step configuration:

{
   "name": "replacetext",
   "searchColumn": "COUNTRY",
   "oldStr": "Fr",
   "newStr": "France"
}

Output dataset:

COMPANYCOUNTRY
Company 1France is boring
Company 2UK

rollup step

Use this step if you need to compute aggregated data at every level of a hierarchy, specified as a series of columns from top to bottom level. The output data structure stacks the data of every level of the hierarchy, specifying for every row the label, level and parent in dedicated columns.

Aggregated rows can be computed with using either sum, average, count, count distinct, min, max, first or last.

{
   "name": "rollup",
   "hierarchy": ["continent", "country", "city"],
   "aggregations": [
   {
      "newcolumns": ["sum_value1", "sum_value2"],
      "aggfunction": "sum",
      "columns": ["value1", "value2"]
    }
    {
      "newcolumns": ["avg_value1"],
      "aggfunction": "avg",
      "columns": ["value1"]
    }
   ],
   "groupby": ["date"],
   "labelCol": "label",
   "levelCol": "level",
   "childLevelCol": "child_level",
   "parentLabelCol": "parent"
}

Example 1 : Basic configuration

Input dataset:

CITYCOUNTRYCONTINENTYEARVALUE
ParisFranceEurope201810
BordeauxFranceEurope20185
BarcelonaSpainEurope20188
MadridSpainEurope20183
BostonUSANorth America201812
New-YorkUSANorth America201821
MontrealCanadaNorth America201810
OttawaCanadaNorth America20187
ParisFranceEurope201913
BordeauxFranceEurope20198
BarcelonaSpainEurope201911
MadridSpainEurope20196
BostonUSANorth America201915
New-YorkUSANorth America201924
MontrealCanadaNorth America201910
OttawaCanadaNorth America201913

Step configuration:

{
   "name": "rollup",
   "hierarchy": ["CONTINENT", "COUNTRY", "CITY"],
   "aggregations": [
    {
      "newcolumns": ["VALUE"],
      "aggfunction": "sum",
      "columns": ["VALUE"]
    }
   ]
}

Output dataset:

CITYCOUNTRYCONTINENTlabellevelchild_levelparentVALUE
EuropeEuropeCONTINENTCOUNTRY64
North AmericaNorth AmericaCONTINENTCOUNTRY112
FranceEuropeFranceCOUNTRYCITYEurope36
SpainEuropeSpainCOUNTRYCITYEurope28
USANorth AmericaUSACOUNTRYCITYNorth America72
CanadaNorth AmericaCanadaCOUNTRYCITYNorth America40
ParisFranceEuropeParisCITYFrance23
BordeauxFranceEuropeBordeauxCITYFrance13
BarcelonaSpainEuropeBarcelonaCITYSpain19
MadridSpainEuropeMadridCITYSpain9
BostonUSANorth AmericaBostonCITYUSA27
New-YorkUSANorth AmericaNew-YorkCITYUSA45
MontrealCanadaNorth AmericaMontrealCITYCanada20
OttawaCanadaNorth AmericaOttawaCITYCanada20

Example 2 : Configuration with optional parameters

Input dataset:

CITYCOUNTRYCONTINENTYEARVALUECOUNT
ParisFranceEurope2018101
BordeauxFranceEurope201851
BarcelonaSpainEurope201881
MadridSpainEurope201831
BostonUSANorth America2018121
New-YorkUSANorth America2018211
MontrealCanadaNorth America2018101
OttawaCanadaNorth America201871
ParisFranceEurope2019131
BordeauxFranceEurope201981
BarcelonaSpainEurope2019111
MadridSpainEurope201961
BostonUSANorth America2019151
New-YorkUSANorth America2019241
MontrealCanadaNorth America2019101
OttawaCanadaNorth America2019131

Step configuration:

{
   "name": "rollup",
   "hierarchy": ["CONTINENT", "COUNTRY", "CITY"],
   "aggregations": [
    {
      "newcolumns": ["VALUE-sum", "COUNT"],
      "aggfunction": "sum",
      "columns": ["VALUE", "COUNT"]
    },
    {
      "newcolumns": ["VALUE-avg"],
      "aggfunction": "avg",
      "columns": ["VALUE"]
    }
   ],
   "groupby": ["YEAR"],
   "labelCol": "MY_LABEL",
   "levelCol": "MY_LEVEL",
   "childLevelCol": "MY_CHILD_LEVEL",
   "parentLabelCol": "MY_PARENT"
}

Output dataset:

CITYCOUNTRYCONTINENTYEARMY_LABELMY_LEVELMY_CHILD_LEVELMY_PARENTVALUE-sumVALUE-avgCOUNT
North America2018EuropeCONTINENTCOUNTRY266.54
North America2018North AmericaCONTINENTCOUNTRY5012.54
FranceEurope2018FranceCOUNTRYCITYEurope157.52
SpainEurope2018SpainCOUNTRYCITYEurope115.52
USANorth America2018USACOUNTRYCITYNorth America3316.52
CanadaNorth America2018CanadaCOUNTRYCITYNorth America178.52
ParisFranceEurope2018ParisCITYFrance10101
BordeauxFranceEurope2018BordeauxCITYFrance551
BarcelonaSpainEurope2018BarcelonaCITYSpain881
MadridSpainEurope2018MadridCITYSpain331
BostonUSANorth America2018BostonCITYUSA12121
New-YorkUSANorth America2018New-YorkCITYUSA21211
MontrealCanadaNorth America2018MontrealCITYCanada10101
OttawaCanadaNorth America2018OttawaCITYCanada771
North America2019EuropeCONTINENTCOUNTRY389.54
North America2019North AmericaCONTINENTCOUNTRY6215.54
FranceEurope2019FranceCOUNTRYCITYEurope2110.52
SpainEurope2019SpainCOUNTRYCITYEurope178.52
USANorth America2019USACOUNTRYCITYNorth America3919.52
CanadaNorth America2019CanadaCOUNTRYCITYNorth America2311.52
ParisFranceEurope2019ParisCITYFrance13131
BordeauxFranceEurope2019BordeauxCITYFrance881
BarcelonaSpainEurope2019BarcelonaCITYSpain11111
MadridSpainEurope2019MadridCITYSpain661
BostonUSANorth America2019BostonCITYUSA15151
New-YorkUSANorth America2019New-YorkCITYUSA24241
MontrealCanadaNorth America2019MontrealCITYCanada10101
OttawaCanadaNorth America2019OttawaCITYCanada13131

select step

Select a column. The default is to keep every columns of the input domain. If the select is used, it will only keep selected columns in the output.

{
    "name": "select",
    "columns": ["my-column", "some-other-column"]
}

Example

Input dataset:

CompanyGroupValueLabel
Company 1Group 113Company 1 - Group 1
Company 2Group 17Company 2 - Group 1
Company 3Group 120Company 3 - Group 1
Company 4Group 21Company 4 - Group 2
Company 5Group 210Company 5 - Group 2
Company 6Group 25Company 6 - Group 2

Step configuration:

{
  {
    "name": "select",
    "columns": ["Value", "Label"]
}
}

Output dataset:

ValueLabel
13Company 1 - Group 1
7Company 2 - Group 1
20Company 3 - Group 1
1Company 4 - Group 2
10Company 5 - Group 2
5Company 6 - Group 2

sort step

Sort values in one or several columns. Order can be either 'asc' or 'desc'. When sorting on several columns, order of columns specified in columns matters.

{
    "name": "sort",
    "columns": [{"column": "foo", "order": "asc"}, {"column": "bar", "order": "desc"}]
}

Example

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
    "name": "sort",
    "columns": [{ "column": "Group", "order": "asc"}, {"column": "Value", "order": "desc" }]
}

Output dataset:

CompanyGroupValue
Label 3Group 120
Label 1Group 113
Label 2Group 17
Label 5Group 210
Label 6Group 25
Label 4Group 21

split step

Split a string column into several columns based on a delimiter.

{
  "name": "split",
  "column": "foo",
  "delimiter": " - ",
  "numberColsToKeep": 3
}

Example 1

Input dataset:

LabelValue
Label 1 - Group 1 - France13
Label 2 - Group 1 - Spain7
Label 3 - Group 1 - USA20
Label 4 - Group 2 - France1
Label 5 - Group 2 - Spain10
Label 6 - Group 2 - USA5

Step configuration:

{
  "name": "split",
  "column": "Label",
  "delimiter": " - ",
  "numberColsToKeep": 3
}

Output dataset:

Label_1Label_2Label_3Value
Label 1Group 1Spain13
Label 2Group 1USA7
Label 3Group 1France20
Label 4Group 2USA1
Label 5Group 2France10
Label 6Group 2Spain5

Example 2: keeping less columns

Input dataset:

LabelValue
Label 1 - Group 1 - France13
Label 2 - Group 1 - Spain7
Label 3 - Group 1 - USA20
Label 4 - Group 2 - France1
Label 5 - Group 2 - Spain10
Label 6 - Group 2 - USA5

Step configuration:

{
  "name": "split",
  "column": "Label",
  "delimiter": " - ",
  "numberColsToKeep": 2
}

Output dataset:

Label_1Label_2Value
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

simplify step

Simplifies geographical data.

When simplifying your data, every point that is closer than a specific distance to the previous one is suppressed. This step can be useful if you have a very precise shape for a country (such as one-meter precision), but want to quickly draw a map chart. In that case, you may want to simplify your data.

After simplification, no points will be closer than tolerance. The unit depends on data's projection and on its unit, but in general, it's expressed in meters for CRS projections. For more details, see the GeoPandas documentation.

Step configuration:

{
  "name": "simplify",
  "tolerance": 1.0
}

substring step

Extract a substring in a string column. The substring begins at index start_index (beginning at 1) and stops at end_index. You can specify negative indexes, in such a case the index search will start from the end of the string (with -1 being the last index of the string). Please refer to the examples below for illustration. Neither start_index nor end_index can be equal to 0.

{
  "name": "substring",
  "column": "foo",
  "startIndex": 1,
  "endIndex": -1,
  "newColumnName": "myNewColumn"
}

Example 1: positive start_index and end_index

Input dataset:

GroupValue
foo13
overflow7
some_text20
a_word1
toucan10
toco5

Step configuration:

{
  "column": "Label",
  "name": "substring",
  "startIndex": 1,
  "endIndex": 4
}
LabelValueLabel_PCT
foo13foo
overflow7over
some_text20some
a_word1a_wo
toucan10touc
toco5toco

Example 2: start_index is positive and end_index is negative

Input dataset:

LabelValue
foo13
overflow7
some_text20
a_word1
toucan10
toco5

Step configuration:

{
  "name": "substring",
  "column": "Label",
  "startIndex": 2,
  "endIndex": -2,
  "newColumnName": "short_label"
}

Output dataset:

LabelValueshort_label
foo13o
overflow7verflo
some_text20ome_tex
a_word1_wor
toucan10ouca
toco5oc

Example 3: start_index and end_index are negative

Input dataset:

LabelValue
foo13
overflow7
some_text20
a_word1
toucan10
toco5

Step configuration:

{
  "name": "substring",
  "column": "Label",
  "startIndex": -3,
  "endIndex": -1
}

Output dataset:

LabelValueLabel_PCT
foo13foo
overflow7low
some_text20ext
a_word1ord
toucan10can
toco5oco

text step

Use this step to add a text column where every value will be equal to the specified text.

{
  {
    "name": "text",
    "newColumn": "new",
    "text": "some text"
  }
}

Example

Input dataset:

LabelValue1
Label 110
Label 21
Label 35

Step configuration:

{
  "name": "text",
  "newColumn": "KPI",
  "text": "Sales"
}

Output dataset:

LabelValue1KPI
Label 110Sales
Label 21Sales
Label 35Sales

todate step

Converts a string column into a date column based on a specified format.

{
    "name": "todate",
    "column": "myTextColumn",
    "format": "%Y-%m-%d"
}

Example

Input dataset:

CompanyDateValue
Company 106/10/201913
Company 107/10/20197
Company 108/10/201920
Company 206/10/20191
Company 207/10/201910
Company 208/10/20195

Step configuration:

{
  "name": "todate",
  "column": "Date",
  "format": "%d/%m/%Y"
}

Output dataset:

CompanyDateValue
Company 12019-10-06T00:00.000Z13
Company 12019-10-07T00:00.000Z7
Company 12019-10-08T00:00.000Z20
Company 22019-10-06T00:00.000Z1
Company 22019-10-07T00:00.000Z10
Company 22019-10-08T00:00.000Z5

top step

Return top N rows by group if groups is specified, else over full dataset.

{
  "name": "top",
  "groups": ["foo"],
  "rankOn": "bar",
  "sort": "desc",
  "limit": 10
}

Example 1: top without groups, ascending order

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "top",
  "rankOn": "Value",
  "sort": "asc",
  "limit": 3
}

Output dataset:

LabelGroupValue
Label 4Group 21
Label 6Group 25
Label 2Group 17

Example 2: top with groups, descending order

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 4Group 21
Label 5Group 210
Label 6Group 25

Step configuration:

{
  "name": "top",
  "groups": ["Group"],
  "rankOn": "Value",
  "sort": "desc",
  "limit": 1
}

Output dataset:

CompanyGroupValue
Label 3Group 120
Label 5Group 210

totals step

Append "total" rows to the dataset for specified dimensions. Computed rows result from an aggregation (either sum, average, count, count distinct, min, max, first or last)

{
  "name": "totals",

  "totalDimensions": [
    { "totalColumn": "foo", "totalRowsLabel": "Total foos" },
    { "totalColumn": "bar", "totalRowsLabel": "Total bars" }
  ],
  "aggregations": [
    {
      "columns": ["value1", "value2"]
      "aggfunction": "sum",
      "newcolumns": ["sum_value1", "sum_value2"]
    },
    {
      "columns": ["value1"],
      "aggfunction": "avg",
      "newcolumns": ["avg_value1"]
    }
   ],
  "groups": ["someDimension"]
}

Example 1: basic usage

Input dataset:

COUNTRYPRODUCTYEARVALUE
Franceproduct A20195
USAproduct A201910
Franceproduct B201910
USAproduct B201915
Franceproduct A202020
USAproduct A202020
Franceproduct B202030
USAproduct B202025

Step configuration:

{
  "name": "totals",
  "totalDimensions": [{ "totalColumn": "COUNTRY", "totalRowsLabel": "All countries" }],
  "aggregations": [
    {
      "columns": ["VALUE"],
      "aggfunction": "sum",
      "newcolumns": ["VALUE"]
    }
   ]
}

Output dataset:

COUNTRYPRODUCTYEARVALUE
Franceproduct A20195
USAproduct A201910
Franceproduct B201910
USAproduct B201915
Franceproduct A202020
USAproduct A202020
Franceproduct B202030
USAproduct B202025
All countriesnullnull135

Example 2: With several totals and groups

Input dataset:

COUNTRYPRODUCTYEARVALUE_1VALUE_2
Franceproduct A2019550
USAproduct A201910100
Franceproduct B201910100
USAproduct B201915150
Franceproduct A202020200
USAproduct A202020200
Franceproduct B202030300
USAproduct B202025250

Step configuration:

{
  "name": "totals",
  "totalDimensions": [
    {"totalColumn": "COUNTRY", "totalRowsLabel": "All countries"},
    {"totalColumn": "PRODUCT", "totalRowsLabel": "All products"}
  ],
  "aggregations": [
    {
      "columns": ["VALUE_1-sum", "VALUE_2"],
      "aggfunction": "sum",
      "newcolumns": ["VALUE_1", "VALUE_2"]
    },
    {
      "columns": ["VALUE_1-avg"],
      "aggfunction": "avg",
      "newcolumns": ["VALUE_1"]
    }
   ],
   "groups": ["YEAR"]
}

Output dataset:

COUNTRYPRODUCTYEARVALUE_2VALUE_1-sumVALUE_1-avg
Franceproduct A20195055
USAproduct A20191001010
Franceproduct B20191001010
USAproduct B20191501515
Franceproduct A20202002020
USAproduct A20202002020
Franceproduct B20203003030
USAproduct B20202502525
USAAll products20204504522.5
FranceAll products20205005025
USAAll products20192502512.5
FranceAll products2019150157.5
All countriesproduct B20205505527.5
All countriesproduct A20204004020
All countriesproduct B20192502512.5
All countriesproduct A2019150157.5
All countriesAll products20209509523.75
All countriesAll products20194004010

trim step

Trim spaces in a column.

{
    "name": "trim",
    "columns": ["my-column", "some-other-column"]
}

Example

Input dataset:

CompanyGroupValueLabel
' Company 1 'Group 113Company 1 - Group 1
' Company 2 'Group 17Company 2 - Group 1

Step configuration:

{
  "name": "trim",
  "columns": ["Company"]
}

Output dataset:

CompanyGroupValueLabel
'Company 1'Group 113Company 1 - Group 1
'Company 2'Group 17Company 2 - Group 1

unpivot step

Unpivot a list of columns to rows.

{
  "name": "unpivot",
  "keep": ["COMPANY", "COUNTRY"],
  "unpivot": ["NB_CLIENTS", "REVENUES"],
  "unpivotColumnName": "KPI",
  "valueColumnName": "VALUE",
  "dropna": true
}

Example 1: with dropnaparameter to true

Input dataset:

COMPANYCOUNTRYNB_CLIENTSREVENUES
Company 1France710
Company 2France2
Company 1USA126
Company 2USA13

Step configuration:

{
  "name": "unpivot",
  "keep": ["COMPANY", "COUNTRY"],
  "unpivot": ["NB_CLIENTS", "REVENUES"],
  "unpivotColumnName": "KPI",
  "valueColumnName": "VALUE",
  "dropna": true
}

Output dataset:

COMPANYCOUNTRYKPIVALUE
Company 1FranceNB_CLIENTS7
Company 1FranceREVENUES10
Company 2FranceNB_CLIENTS2
Company 1USANB_CLIENTS12
Company 1USAREVENUES6
Company 2USANB_CLIENTS1
Company 2USAREVENUES3

Example 1: with dropnaparameter to false

Input dataset:

COMPANYCOUNTRYNB_CLIENTSREVENUES
Company 1France710
Company 2France2
Company 1USA126
Company 2USA13

Step configuration:

{
  "name": "unpivot",
  "keep": ["COMPANY", "COUNTRY"],
  "unpivot": ["NB_CLIENTS", "REVENUES"],
  "unpivotColumnName": "KPI",
  "valueColumnName": "VALUE",
  "dropna": false
}

Output dataset:

COMPANYCOUNTRYKPIVALUE
Company 1FranceNB_CLIENTS7
Company 1FranceREVENUES10
Company 2FranceNB_CLIENTS2
Company 2FranceREVENUES
Company 1USANB_CLIENTS12
Company 1USAREVENUES6
Company 2USANB_CLIENTS1
Company 2USAREVENUES3

uppercase step

Converts a string column to uppercase.

{
  "name": "uppercase",
  "column": "foo"
}

Example:

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120

Step configuration:

{
  "name": "uppercase",
  "column": "Label"
}

Output dataset:

LabelGroupValue
LABEL 1Group 113
LABEL 2Group 17
LABEL 3Group 120

uniquegroups step

Allow to get unique groups of values from one or several columns.

{
  "name": "uniquegroups",
  "on": ["foo", "bar"]
}

Example:

Input dataset:

LabelGroupValue
Label 1Group 113
Label 2Group 17
Label 3Group 120
Label 1Group 21
Label 2Group 12
Label 3Group 13

Step configuration:

{
  "name": "uniquegroups",
  "column": ["Label", "Group"]
}

Output dataset:

LabelGroup
Label 1Group 1
Label 1Group 2
Label 2Group 1
Label 3Group 1

waterfall step

This step allows to generate a data structure useful to build waterfall charts. It breaks down the variation between two values (usually between two dates) accross entities. Entities are found in the labelsColumn, and can optionally be regrouped under common parents found in the parentsColumn for drill-down purposes.

{
  "name": "waterfall",
  "valueColumn": "VALUE",
  "milestonesColumn": "DATE",
  "start": "2019",
  "end": "2020",
  "labelsColumn": "PRODUCT",
  "groupby": ["COUNTRY"],
  "sortBy": "value",
  "order": "desc"
}

Example 1: Basic usage

Input dataset:

cityyearrevenue
Bordeaux2019135
Boston2019275
New-York2019115
Paris2019450
Bordeaux201898
Boston2018245
New-York2018103
Paris2018385

Step configuration:

{
  "name": "waterfall",
  "valueColumn": "revenue",
  "milestonesColumn": "year",
  "start": "2018",
  "end": "2019",
  "labelsColumn": "city",
  "sortBy": "value",
  "order": "desc"
}

Output dataset:

LABEL_waterfallTYPE_waterfallrevenue
2018null831
Parisparent65
Bordeauxparent37
Bostonparent30
New-Yorkparent12
2019null975

Example 2: With more options

Input dataset:

citycountryproductyearrevenue
BordeauxFranceproduct1201965
BordeauxFranceproduct2201970
ParisFranceproduct12019210
ParisFranceproduct22019240
BostonUSAproduct12019130
BostonUSAproduct22019145
New-YorkUSAproduct1201955
New-YorkUSAproduct2201960
BordeauxFranceproduct1201838
BordeauxFranceproduct2201860
ParisFranceproduct12018175
ParisFranceproduct22018210
BostonUSAproduct1201895
BostonUSAproduct22018150
New-YorkUSAproduct1201850
New-YorkUSAproduct2201853

Step configuration:

{
  "name": "waterfall",
  "valueColumn": "revenue",
  "milestonesColumn": "year",
  "start": "2018",
  "end": "2019",
  "labelsColumn": "city",
  "parentsColumn": "country",
  "groupby": ["product"],
  "sortBy": "label",
  "order": "asc"
}

Output dataset:

LABEL_waterfallGROUP_waterfallTYPE_waterfallproductrevenue
20182018nullproduct1358
20182018nullproduct2473
BordeauxFrancechildproduct127
BordeauxFrancechildproduct210
BostonUSAchildproduct135
BostonUSAchildproduct2-5
FranceFranceparentproduct240
FranceFranceparentproduct162
New-YorkUSAchildproduct15
New-YorkUSAchildproduct27
ParisFrancechildproduct135
ParisFrancechildproduct230
USAUSAparentproduct22
USAUSAparentproduct140
20192019nullproduct2515
20192019nullproduct1460

On this page

absolutevalue stepExampleaddmissingdates stepExample 1: day granularity without groupsExample 2: day granularity with groupsExample 3: month granularityaggregate stepExample 1: keepOriginalGranularity set to falseExample 2: keepOriginalGranularity set to trueappend stepExampleargmax stepExample 1: without groupsExample 2: with groupsargmin stepExample 1: without groupsExample 2: with groupscomparetext stepExampleconcatenate stepExampleconvert stepExamplecumsum stepExample 1: Basic usageExample 2: With more advanced optionsdateextract stepExampledatetimefromparts stepdategranularity stepExampledelete stepExampleduplicate stepExampleduration stepExample 1: duration in daysExample 2: duration in minutesevolution stepExample 1: Basic configuration - evolution in absolute valueExample 2: Basic configuration - evolution in percentageExample 3: Error on duplicate datesExample 4: Complete configuration with index columnsfillna stepExamplefilter stepRelative datesformula stepSupported operatorsExample 1: Basic usageExample 2: Column name with whitespacesifthenelse stepExamplejoin stepExample 1: Left join with one column couple as on parameterExample 2: inner join with different column names in the on parameterfromdate stepExamplelowercase stepExample:movingaverage stepExample 1: Basic usageExample 2: with groups and custom newColumnNamepercentage stepExample:pivot stepExample:statistics stepExample:rank stepExample 1: Basic usageExample 2: With more optionsrename stepExample:replace stepExamplereplacetext stepExamplerollup stepExample 1 : Basic configurationExample 2 : Configuration with optional parametersselect stepExamplesort stepExamplesplit stepExample 1Example 2: keeping less columnssimplify stepsubstring stepExample 1: positive start_index and end_indexExample 2: start_index is positive and end_index is negativeExample 3: start_index and end_index are negativetext stepExampletodate stepExampletop stepExample 1: top without groups, ascending orderExample 2: top with groups, descending ordertotals stepExample 1: basic usageExample 2: With several totals and groupstrim stepExampleunpivot stepExample 1: with dropnaparameter to trueExample 1: with dropnaparameter to falseuppercase stepExample:uniquegroups stepExample:waterfall stepExample 1: Basic usageExample 2: With more options