The most common expression you will use for data-driven visualizations is
ramp a special CARTO VL expression that outputs values based on an input.
Depending on the type of input, the matching output is performed in two different ways:
Throughout this guide, you will explore different ways to use
ramp to match inputs to values. The most common use case is to match a property in your data as the input to fixed constant outputs like color or size. This is what we call style by value.
The following sections will cover style by value for different data properties and map types. For example, by the end of this guide, you will better understand the options available when dealing with something like a transaction dataset and how to style by numeric data like the amount of each payment, or by categorical data like the method of payment (credit card, cash, etc.).
To introduce the use of
ramp, this guide covers use-cases with the styling property
ramp values don’t always have to be colors.
ramp gives you the ablitiy to create a variety of map types like bubble, flow, and more which we will explore in more detail in Part 2 of this guide.
It is common to want to map a continuous range of numeric data, like population density, to a continuous range of colors, for example, the range of colors between black and yellow. This is straight-forward with CARTO VL.
The style below assigns the feature with the lowest population density in the source data to
midnightblue and the feature with the highest population density to
gold. Intermediate population densities are colored based on the interpolation between
gold based on how close a value is to the lowest and highest values in the dataset.
color: ramp($population_density, [midnightblue, gold])
To see more variation in the data, you can even set intermediate colors in the color list for example, here we are adding an intermediate color,
color: ramp($population_density, [midnightblue, deeppink, gold])
Matching the input with the context of the lowest population density and highest population density is done by the
linear function, which is used automatically by
ramp when the input is a numeric property. This means that the CARTO VL
ramp function makes transformations that we call implicit casts.
Use the map below to toggle between three styles. You will notice that the map does not change since Style 1 is implicity cast to Style 2 which is implicitly cast to Style 3, making them all equal. In the following section, you will see how to take advantage of this behavior to further customize your map.
// Style 1: this will be implicitly cast to Style 2 color: ramp($population_density,[midnightblue, deeppink, gold]) // Style 2: will be implicitly cast to Style 3 color: ramp($population_density, [midnightblue, deeppink, gold]) // Style 3 color: ramp(linear($population_density, globalMin($population_density), globalMax($population_density)), [midnightblue, deeppink, gold])
linear is called with only one parameter (as seen in Style 2 above), it will transform to what we see in Style 3:
color: linear($population_density, globalMin($population_density), globalMax($population_density))
The second and third parameters of
globalMax()) are what set the values of the lowest and highest population densities for
It is common for datasets to have outliers with values that are very far away from the norm. There are times where you will want to “ignore” these outliers when computing a
ramp. With CARTO VL, this can be done by manually setting explicit ranges for the second and third parameters of
linear to the minimum and maximum values of the data range you are interested in.
In the map below, as you toggle between styles, you will notice how Style 4 and Style 5 change based on the modifications made to second (minimum) and third (maximum) parameters.
// Style 3: equivalent to Style 3 above color: ramp(linear($dn, globalMin($dn), globalMax($dn)), [midnightblue, deeppink, gold]) // Style 4: the data range has been fixed to the [0, 160] range color: ramp(linear($dn, 0, 160), [midnightblue, deeppink, gold]) // Style 5: the data range has been set to avoid taking into account the first 1% of the data and the last 1% of the data color: ramp(linear($dn, globalPercentile($dn, 1), globalPercentile($dn, 99)), [midnightblue, deeppink, gold])
linear reduces the loss of precision compared to the usage of classifiers. However, correctly classified data makes it easier to detect patterns in data since it is difficult to perceive small differences in color or size, which can arise when using
There are multiple classification methods aviailable in CARTO VL (quantiles, equal intervals and standard deviation). These classification methods can be applied using two different samples of data:
global*classifiers will apply the classification to all source data. Ignoring filters or the presence of each feature in the viewport.
viewport*classifiers will apply the classification only to the features that are in the viewport. This includes filtering by the
filterstyling property and filtering by checking that the feature is within the region covered by the screen at each moment. Changes in the view (map center/map zoom) will trigger an automatic re-computation of the classification.
Learn more about using
viewport* methods in the Aggregations guide.
Use the map below to see how classification of data varies between these two sample types:
// Style 1: Quantiles with 3 class breaks (global). The first bucket contains the lower 33% of the data, the second the middle 33%, and the third, the last 33%. color: ramp(globalQuantiles($dn, 3), [midnightblue, deeppink, gold]) // Style 2: Equal intervals with 3 class breaks (global). The range of data is divided by the number of class breaks, giving the common difference. color: ramp(globalEqIntervals($dn, 3), [midnightblue, deeppink, gold]) // Style 3: Quantiles with 3 class breaks (viewport). color: ramp(viewportQuantiles($dn, 3), [midnightblue, deeppink, gold]) // Style 4: Equal Intervals classification equivalent to Style 2 but only using the samples that are shown in the viewport. color: ramp(viewportEqIntervals($dn, 3), [midnightblue, deeppink, gold])
Do you see how
viewport* classifiers are dynamic and change the results according to the map bounds? Be sure to keep an eye on the dynamic legend!
You can also classify data with a fixed list of breakpoints (manual classification) with the
buckets() function. For example, the expression
buckets($price, [10, 200]) will classify features, based on their value into 3 different buckets: features that have a price less than 10,features that have a price between 10 and 200, and features that have a price higher than 200.
It’s important to note that there is always one more class break than set breakpoints. The
buckets function can also be used with categorical inputs, we’ll explore that functionality later in this guide.
// Style 1: Features with population density less than 80 will be set midnightblue, between 80 and 160 will be set deeppink, and greater than 160 will be set gold. color: ramp(buckets($dn, [80, 160]), [midnightblue, deeppink, gold])
filter: is a special styling property. Apart from multiplying the feature’s color alpha channel by its value, it is used semantically to filter the dataset, which affects the
viewport* classifiers and
viewport* aggregators. When a feature’s
filter: value is above
0.5 we consider that the feature pass the filter, and the feature will be taken into account. When the value is below
0.5, the feature is ignored (treated as non-existent) in all
Of course, not all data is numeric. Sometimes, it’s just one value of a fixed number of possible values. For example, in an election map, there are a fixed number of political parties. And in a geographic region, only one party can win. This is what we refer to as categorical data.
In this section, we will explore a variety of ways to symbolize categorical data:
Note: Before starting with your category map, it is important to note that in CARTO VL only string properties in the Source are considered categorical. This means that if you have a category encoded as a number, it is treated as a number. Therefore, functions that expect categorical properties won’t work. Likewise, numerical properties encoded as strings will be treated as categories and functions that expect numerical properties won’t work. As a rule of thumb, in CARTO VL, if you want to apply numeric functions (addition, multiplication, etc.), the property should be stored/encoded as numbers.
To assign a specific color to a specific category in your data, use the
buckets you can pick some or all categories from a property. You can list them in a particular order, and use
ramp to do a one-to-one match between those categories and an associated list of colors.
The map below is a categorical map of election results in the UK. Using a field (
$winner), regions where the Conseravative Party won are colored
royalblue and regions where the Labour Party won are colored
crimson. These two parties are matched to their unique color using
// Color regions where the conservatives won blue and progressives red color: ramp(buckets($winner, ["Conservative Party", "Labour Party"]), [royalblue, crimson])
In the map above, any region where a party other than Conservative or Labour won is colored
gray by default. This is because in the data, there are additional political parties.
Since the other winning parties weren’t placed in the
bucket function list, they are automatically assigned to a
others bucket. Once you use
buckets any category that isn’t explicitly defined, will be sent to this bucket. If you want to display more categories, you can add them to the list and assign them a color.
If you want to overwrite the defualt
others color (
gray), you can add a third parameter to
ramp. In this case, all other parties will be colored
// Overwrite the default others color to orange ramp(buckets($winner, ['conservatives', 'progressives'], [royalblue,crimson], orange)
Another useful function for coloring categorical data is
top allows you to select a number of most commonly occuring categories in a dataset and assign them a color. Similar to the map above, remaining categories are assigned to the
The map below visually summarizes the top three most common weather conditions for rail accidents in the US between the years of 2010-2014 using the
top function. The top three categories are matched to the listed colors (
darkturquoise) and all other weather conditions are colored
white in the others bucket:
color: ramp(top($weather, 3), [darkorange,darkviolet,darkturquoise], white)
There are times, in the initial phases of exploring a dataset, where it is helpful to have all categories in a property assigned a color. This is the default behavior in CARTO VL if you use a property as the
ramp input (with no
buckets) and a color list.
In the rail accident dataset, there are six types of weather conditions defined. In the map below, each type of condition is assigned a color even though there are only three colors in the list. To generate these intermediate colors, CARTO VL interpolates between the ones provided because the number of colors doesn’t match the number of categories in the input.
As mentioned above, this is a useful method for exploring data and/or if there are fewer categories in your dataset. If you have a dataset with over 11 categories, we recommend using
top since it is difficult for the human eye to distinguish between so many different colors.
The color interpolation done by
ramp is always in the CIELab color space. This is especially important the sRGB color space is not a perceptual one. CIELab assures a better perception of color since it models, more closely, the way the human eye perceives color. If for example, you are interpolating between two colors, (colorA and colorB) CIELab interploation will be at 50% (in the middle) between them which is not the case in sRGB.