Repository: streamlit/streamlit

Issue:
st.map() fails with zoom error for small number of points
# Summary

In this [forum post](https://discuss.streamlit.io/t/plot-map-with-address-from-user-input/2950), the user highlights that `st.map()` does not plot a single point for the map. To troubleshoot, I opened up the Chrome console, saw a "Zoom must be set error" message in regards to the map.

# Solution

Adding a non `None` zoom value in the `st.map()` call [resolves the issue](https://discuss.streamlit.io/t/plot-map-with-address-from-user-input/2950/3?u=randyzwitch). Need a heuristic for a "small" number of points where `st.map()` automatically adds an integer value for the `zoom` parameter. At larger volumes of data, `zoom =None` seems to be ok, and deck.gl infers the proper zoom level based on the bounding box of data points.
st.map() fails with zoom error for small number of points
# Summary

In this [forum post](https://discuss.streamlit.io/t/plot-map-with-address-from-user-input/2950), the user highlights that `st.map()` does not plot a single point for the map. To troubleshoot, I opened up the Chrome console, saw a "Zoom must be set error" message in regards to the map.

# Solution

Adding a non `None` zoom value in the `st.map()` call [resolves the issue](https://discuss.streamlit.io/t/plot-map-with-address-from-user-input/2950/3?u=randyzwitch). Need a heuristic for a "small" number of points where `st.map()` automatically adds an integer value for the `zoom` parameter. At larger volumes of data, `zoom =None` seems to be ok, and deck.gl infers the proper zoom level based on the bounding box of data points.


Discussion:

Resolving patch:
diff --git a/lib/streamlit/elements/map.py b/lib/streamlit/elements/map.py
--- a/lib/streamlit/elements/map.py
+++ b/lib/streamlit/elements/map.py
@@ -79,6 +79,7 @@ def map(dg, data=None, zoom=None, use_container_width=True):
 
 # Other default parameters for st.map.
 _DEFAULT_COLOR = [200, 30, 0, 160]
+_DEFAULT_ZOOM_LEVEL = 12
 _ZOOM_LEVELS = [
     360,
     180,
@@ -100,6 +101,7 @@ def map(dg, data=None, zoom=None, use_container_width=True):
     0.003,
     0.001,
     0.0005,
+    0.00025,
 ]
 
 
@@ -116,10 +118,14 @@ def _get_zoom_level(distance):
     Returns
     -------
     int
-        The zoom level, from 0 to 29.
+        The zoom level, from 0 to 20.
 
     """
 
+    # For small number of points the default zoom level will be used.
+    if distance < _ZOOM_LEVELS[-1]:
+        return _DEFAULT_ZOOM_LEVEL
+
     for i in range(len(_ZOOM_LEVELS) - 1):
         if _ZOOM_LEVELS[i + 1] < distance <= _ZOOM_LEVELS[i]:
             return i


Test patch:
diff --git a/lib/tests/streamlit/map_test.py b/lib/tests/streamlit/map_test.py
--- a/lib/tests/streamlit/map_test.py
+++ b/lib/tests/streamlit/map_test.py
@@ -18,7 +18,7 @@
 import numpy as np
 import json
 
-from streamlit.elements.map import _DEFAULT_MAP
+from streamlit.elements.map import _DEFAULT_MAP, _DEFAULT_ZOOM_LEVEL
 from tests import testutil
 import streamlit as st
 
@@ -58,6 +58,14 @@ def test_default_map_copy(self):
         st.map(df1)
         self.assertEqual(_DEFAULT_MAP["initialViewState"]["latitude"], 0)
 
+    def test_default_zoom_level(self):
+        """Test that _DEFAULT_ZOOM_LEVEL is set if zoom is not provided and distance is too small."""
+        df = pd.DataFrame({"lat": [1], "lon": [1]})
+        st.map(df)
+
+        c = json.loads(self.get_delta_from_queue().new_element.deck_gl_json_chart.json)
+        self.assertEqual(c.get("initialViewState").get("zoom"), _DEFAULT_ZOOM_LEVEL)
+
     def test_map_leak(self):
         """Test that maps don't stay in memory when you create a new blank one.