# Visualizing NYC Taxi Trends with Kepler.gl

In my [last post](https://blog.mtran.me/preprocessing-nyc-taxi-trip-data-with-python), 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](http://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](http://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](http://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](https://cdn.hashnode.com/res/hashnode/image/upload/v1748551185156/3c76f7b8-02b0-45bf-85b8-76bf2622bbf8.png align="center")

---

## 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.](https://cdn.hashnode.com/res/hashnode/image/upload/v1748545875309/3f92519e-842d-4453-8d62-8be09a9ff476.png align="center")

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](https://cdn.hashnode.com/res/hashnode/image/upload/v1748551136749/94705cf7-18c2-4dc5-bcba-3f80eeabe4c0.png align="center")

---

## 5\. Getting a Sharper Export

To export a high-quality map snapshot:

1. Click the **three-dot menu &gt; 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.
