Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Applies to: ✅ Azure Data Explorer ✅ Azure Monitor ✅ Microsoft Sentinel
Use the Kusto Query Language (KQL) to create geospatial visualizations. Geospatial clustering organizes data by location. KQL provides multiple geospatial clustering methods and geospatial visualization tools.
In this tutorial, you learn how to:
Prerequisites
To run the queries, you need a query environment that has access to the sample data. Use one of the following:
- Microsoft account or Microsoft Entra user identity to sign in to the help cluster
- Microsoft account or Microsoft Entra user identity to sign in to the help cluster
Use project to select the longitude column, then the latitude column. Use render to show the points on a map (scatter chart with kind
set to map
).
Plot points on a map
Use project to select the longitude column, then the latitude column. Use render to show the points on a map (scatter chart with kind
set to map
).
StormEvents
| take 100
| project BeginLon, BeginLat
| render scatterchart with (kind = map)
Plot multiple series of points
To visualize multiple point series, use project to select the longitude, latitude, and a third column that defines the series.
In the following query, the series is EventType
. The points use different colors by EventType
and, when selected, display the EventType
value.
StormEvents
| take 100
| project BeginLon, BeginLat, EventType
| render scatterchart with (kind = map)
When the result has more columns than the longitude, latitude, and series columns, you can also explicitly specify the xcolumn
(longitude), ycolumn
(latitude), and series
in the render
operator.
StormEvents
| take 100
| render scatterchart with (kind = map, xcolumn = BeginLon, ycolumns = BeginLat, series = EventType)
Use GeoJSON values to plot points on a map
Dynamic GeoJSON values update frequently and are used in real-time mapping. Mapping points with dynamic GeoJSON values gives you flexibility and control that plain latitude and longitude can't provide.
The following query uses the geo_point_to_s2cell and geo_s2cell_to_central_point functions to map storm events on a scatter chart.
StormEvents
| project BeginLon, BeginLat
| summarize by hash=geo_point_to_s2cell(BeginLon, BeginLat, 5)
| project point = geo_s2cell_to_central_point(hash)
| project lng = toreal(point.coordinates[0]), lat = toreal(point.coordinates[1])
| render scatterchart with (kind = map)
Represent data points with variable sized bubbles
Visualize data distribution by aggregating each cluster and plotting its central point.
For example, the following query filters storm events where EventType is Tornado
. It groups events into longitude and latitude clusters, counts events in each cluster, projects each cluster's central point, and renders a map. Regions with the most tornadoes stand out by their larger bubble size.
StormEvents
| where EventType == "Tornado"
| project BeginLon, BeginLat
| where isnotnull(BeginLat) and isnotnull(BeginLon)
| summarize count_summary=count() by hash = geo_point_to_s2cell(BeginLon, BeginLat, 4)
| project geo_s2cell_to_central_point(hash), count_summary
| extend Events = "count"
| render piechart with (kind = map)
Display points within a specific area
Use a polygon to define the region and the geo_point_in_polygon function to filter for events that occur within that region.
The following query defines a polygon representing the southern California region and filters for storm events within this region. It then groups the events into clusters, counts the number of events in each cluster, projects the central point of the cluster, and renders a map to visualize the clusters.
let southern_california = dynamic({
"type": "Polygon",
"coordinates": [[[-119.5, 34.5], [-115.5, 34.5], [-115.5, 32.5], [-119.5, 32.5], [-119.5, 34.5]]
]});
StormEvents
| where geo_point_in_polygon(BeginLon, BeginLat, southern_california)
| project BeginLon, BeginLat
| summarize count_summary = count() by hash = geo_point_to_s2cell(BeginLon, BeginLat, 8)
| project geo_s2cell_to_central_point(hash), count_summary
| extend Events = "count"
| render piechart with (kind = map)
Show nearby points on a LineString
The following query finds nearby storm events that occur along a specified LineString, which represents a defined path. In this case, the LineString is a road to Key West. The geo_distance_point_to_line() function is used to filter the storm events based on their proximity to the defined LineString. If an event is within 500 meters from LineString, the event is rendered on a map.
let roadToKeyWest = dynamic({
"type":"linestring",
"coordinates":[
[
-81.79595947265625,
24.56461038017685
],
[
-81.595458984375,
24.627044746156027
],
[
-81.52130126953125,
24.666986385216273
],
[
-81.35650634765625,
24.66449040712424
],
[
-81.32354736328125,
24.647017162630366
],
[
-80.8099365234375,
24.821639356846607
],
[
-80.62042236328125,
24.93127614538456
],
[
-80.37872314453125,
25.175116531621764
],
[
-80.42266845703124,
25.19251511519153
],
[
-80.4803466796875,
25.46063471847754
]
]});
StormEvents
| where isnotempty(BeginLat) and isnotempty(BeginLon)
| project BeginLon, BeginLat, EventType
| where geo_distance_point_to_line(BeginLon, BeginLat, roadToKeyWest) < 500
| render scatterchart with (kind=map)
Show nearby points in a polygon
The following query finds nearby storm events that occur within a specified polygon. In this case, the polygon is a road to Key West. The geo_distance_point_to_polygon() function is used to filter the storm events based on their proximity to the defined polygon. If an event is within 500 meters of the polygon, the event is rendered on a map.
let roadToKeyWest = dynamic({
"type":"polygon",
"coordinates":[
[
[
-80.08209228515625,
25.39117928167583
],
[
-80.4913330078125,
25.517657429994035
],
[
-80.57922363281249,
25.477992320574817
],
[
-82.188720703125,
24.632038149596895
],
[
-82.1942138671875,
24.53712939907993
],
[
-82.13104248046875,
24.412140070651528
],
[
-81.81243896484375,
24.43714786161562
],
[
-80.58746337890625,
24.794214972389486
],
[
-80.08209228515625,
25.39117928167583
]
]
]});
StormEvents
| where isnotempty(BeginLat) and isnotempty(BeginLon)
| project BeginLon, BeginLat, EventType
| where geo_distance_point_to_polygon(BeginLon, BeginLat, roadToKeyWest) < 500
| render scatterchart with (kind=map)
Find anomalies based on geospatial data
The following query performs an analysis of storm events occurring within a particular state. The query uses S2 cells and temporal aggregation to investigate patterns of damage. The result is a visual anomaly chart that portrays any irregularities or deviations in storm-induced destruction over time, offering a detailed perspective on the effect of storms within the specified state boundaries.
let stateOfInterest = "Texas";
let statePolygon = materialize(
US_States
| extend name = tostring(features.properties.NAME)
| where name == stateOfInterest
| project geometry=features.geometry);
let stateCoveringS2cells = statePolygon
| project s2Cells = geo_polygon_to_s2cells(geometry, 9);
StormEvents
| extend s2Cell = geo_point_to_s2cell(BeginLon, BeginLat, 9)
| where s2Cell in (stateCoveringS2cells)
| where geo_point_in_polygon(BeginLon, BeginLat, toscalar(statePolygon))
| make-series damage = avg(DamageProperty + DamageCrops) default = double(0.0) on StartTime step 7d
| extend anomalies=series_decompose_anomalies(damage)
| render anomalychart with (anomalycolumns=anomalies)
Related content
- See a use case for geospatial clustering: Data analytics for automotive test fleets
- Learn about Azure architecture for geospatial data processing and analytics