Visualizing NYC Taxi Trends with Kepler.gl

Martin TranMartin Tran
3 min read

In my last post, I walked through how to clean and prepare NYC taxi data with Python — merging multiple years of trip data, resolving zone IDs into boroughs, and engineering useful time features like hour, day_of_week, and timestamp. This time, I’m taking that cleaned dataset (kepler_zone_heatmap_detailed.csv) and building a visual story with it using Kepler.gl.

Here’s how I set it up.


1. What’s in the Data?

This dataset includes hourly pickup counts grouped by NYC taxi zones, already joined with centroid coordinates. Each row represents a zone snapshot, and columns include:

  • Latitude, Longitude: Coordinates for the zone center

  • trip_count: Number of pickups at that location and time

  • hour, day_of_week, day, day_of_year: Temporal granularity for filtering

    • day stands for day of month (e.g. comparing traffic on December 25th compared to December 1st)
  • timestamp: Rounded datetime used for animation/slider

  • Zone, Borough: For labeling or aggregation later

This isn’t raw GPS data — it’s zone-level aggregation, which makes visualization both faster and more interpretable.


2. Uploading to Kepler.gl

  • Go to kepler.gl/demo and browse for or click and drag the kepler_zone_heatmap_detailed.csv into the pop-up dialogue

  • Upload kepler_zone_heatmap_detailed.csv

  • In my experience, Kepler.gl does not auto-detect Latitude and Longitude. You’ll have to manually confirm or set those in the layer config.


3. Creating the Heatmap (Point Layer Style)

While Kepler offers multiple layer types, I found better clarity using a Point Layer instead of a Heatmap. Here's how I configured it:

  • Layer Type: Point

  • Fill Color: Set based on trip_count

  • Color Gradient: I changed the scale from white to red — this gave better contrast for spotting high-demand zones

  • Radius: Adjust for visibility based on zoom; I used 10 — which is the default

The result makes it much easier to distinguish heavily trafficked areas like Midtown Manhattan or JFK Airport during rush hour.

Sundays at 10:00 PM


4. Enabling Time Playback

To get temporal playback:

  • Go to the Filters tab

  • Add a filter on timestamp

  • Click on the "time playback" button to enable animation

  • You can also add filters for day_of_week or hour to explore weekday vs weekend patterns

Including all the filters makes it too granular, so you will have to play around with the combinations.

This let me visualize how demand shifts over time — morning rush in Midtown, late-night clusters in nightlife zones, etc.

Sundays at 4:00 AM


5. Getting a Sharper Export

To export a high-quality map snapshot:

  1. Click the three-dot menu > Export Image

  2. Choose resolution (I used 2x for clarity) and aspect ratio (16:9 works great for blog banners)

If that’s not to your liking, you could always take a screenshot. I prefer to take screenshots (which the pictures above are screenshots) since you can zoom into the map.

The issue with exporting a snapshot is the fact that it is harder to tell which points has changed and which ones have not. Kepler.gl has an option to export the map you created as a HTML file in which other users can access it. However, the dataset I produced made a 300MB resulting file, which is large for web users to view.


6. What’s Next?

While Kepler.gl is rudimentary, I’ve got a clear visual of when and where taxi demand spikes. But I want to take it a step further — combining this with trip profitability (fare + tips) and estimated travel time or congestion to recommend optimal pickup zones at any given hour. Think of it like a driver-facing AI assistant.

More on that in the next post.


Want to explore this yourself? The dataset’s light enough to run locally, and tools like Kepler.gl make this type of exploration a breeze without needing any frontend code.

Let me know what visual trends you notice — especially if you find hidden hotspots I missed.

0
Subscribe to my newsletter

Read articles from Martin Tran directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Martin Tran
Martin Tran