In the first post of this series, I mentioned a good way to determine which way to visualize your data is to ask questions about the purpose of the map. In addition to “where things are,” which we already examined in that post, you may also want answer questions like:
- What chain does each restaurant belong to in my city?
- What is the most predominant crop of each county in the US?
- What level of crime risk does each census tract have?
Unique value renderer is good for answering your what questions.
The unique value renderer looks at an attribute field in your layer, and provides a symbol for each unique value in that field. In this sample, we will again use the National Park Service Units dataset. The resulting map shows each unit with its own type, such as “national park”, “national monument”, etc.
Create a unique value renderer
The way to create a unique value renderer is very similar to the way you create a simple renderer, which we have introduced in the first post. The key difference is you need to pass an extra argument into the UniqueValueRenderer
constructor: a field name. This field’s values will determine which symbol is used for each feature on the map. In this sample, we choose the field "Type"
var symbol = new SimpleMarkerSymbol();
symbol.setColor(new Color("#cccccc"));
var renderer = new UniqueValueRenderer(symbol, "Type");
The symbol
object above is the default symbol for your data.
Define symbols for the unique values
The whole purpose of a map that answers what questions is to clearly show features on the map, logically grouped by something they have in common, as designated by their unique value in a field. To accomplish this, create symbols which relate to the subject, but are different enough from one another that patterns can emerge on the map. Defining symbols is an iterative process: try something, then modify based on feedback.
To specify a unique symbol for each unique value in the Type
field, you can use the addValue()
method to pass a each value with its unique symbol:
var symbol1 = new SimpleMarkerSymbol();
symbol1.setColor(new Color("#ed5151"));
renderer.addValue("National Park", symbol1);
var symbol2 = new SimpleMarkerSymbol();
symbol2.setColor(new Color("#149ece"));
renderer.addValue("National Monument", symbol2);
It might not be necessary to provide unique symbols for all values in the field. In fact, your audience can hardly distinguish more than ten different colors. We recommend you only add symbols for the top few categories, and group all the others into a group called “others.” The rest will automatically get the default symbol, which is defined in the UniqueValueRenderer
constructor.
Follow this link to see a completed sample.
As we put more than one color on the map, you may also want to add legend to your app. A similar sample with legend is available. We will take a closer look at legend in the next post.
One step further: convert raw data to pre-defined categories on the fly
Sometimes you have a field with too many unique values, which make it hard to create a good visualization based on that field. One nice trick you can use with the unique value renderer is to convert raw data to a few pre-defined categories, on the fly. For example, instead of taking raw values in the "Address"
field, if you would like to group data in a few categories like “Pacific West”, “Great Plains”, etc. based on the state name in the address, you can take advantage of this trick to convert data on client-side.
Converting raw values on the fly saves you the step of having to add a field to the data and calculate it, if that is something you don’t wish to do or cannot do.
This magic starts with the creation of the renderer:
var renderer = new UniqueValueRenderer(symbol, function(graphic){
...
});
For the second parameter in the renderer, instead of passing a field name (string), you provide a function to convert values in that field. This function gives you access to every graphic in the layer. Each graphic object contains all properties you need to show it on map, including geometry, attributes, etc.
Based a field "Address"
, we can convert the address into three categories: pacific west and other areas. We use graphic.attributes['Address']
to access this field. If an address contains state abbreviation CA, OR or WA, we categorize it as pacific west.
var renderer = new UniqueValueRenderer(null, function(graphic){
if (graphic.attributes['Address'].indexOf("CA") !== -1 || graphic.attributes['Address'].indexOf("OR") !== -1 || graphic.attributes['Address'].indexOf("WA") !== -1) {
return "Pacific West";
} else {
return "Other Areas";
};
});
Following the creation of the renderer, we also need to provide symbols for these newly converted categories:
var symbol1 = new SimpleMarkerSymbol();
symbol1.setColor(new Color("#7b3578"));
renderer.addValue("Pacific West", symbol1);
var symbol2 = new SimpleMarkerSymbol();
symbol2.setColor(new Color("#cccccc"));
renderer.addValue("Other Areas", symbol2);
A finalized application can be found here. Using function in unique value renderer allows you to visualize not only the raw data in your feature layer, but also new information calculated from your raw values.
What’s coming next
This technique is actually very powerful. A few posts later, we will introduce predominance mapping, which utilizes this method to mine hidden stories from multiple columns of data. Before then, we will look at different ways to visualize numerical (quantitative) data, as well as how to add pop-up and legend to your apps.