# Put a geographical map on the floor of a Scatter3D to track coronavirus infection events

**URL:** <https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335>\
**Category:** 📊 Plotly Python\
**Created:** [March 18, 2020, 12:52am UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335 "2020-03-18T00:52:57Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![jonschull](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jonschull/32/9202_2.png) [@jonschull](https://community.plotly.com/u/jonschull)\
**Post date:** [March 18, 2020, 12:52am UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335/1 "2020-03-18T00:52:58Z")

</div>

To help people track possible Covid/Coronavirus infection events, I’m trying to use Google Location History Data from multiple individuals to show intersections in time and space.

 ![Pasted_Image_3_17_20__8_55_PM](https://us1.discourse-cdn.com/flex024/uploads/plot/original/2X/c/c66e54a1b0925c8f8e3e7efc8a5a4bf935ee7cf2.jpeg)

In the upper figure, you see my location history on a conventional map. In the lower figure, you see a Scatter3D plot with x=latitude, y=longitude, z=time. (Yes I went to Costa Rica recently).

Now, **I’d like a conventional map to be laid on the “floor” of the 3d plot.**

[It’s possible in principle](https://plot.ly/python/v3/2d-projection-of-3d-surface/#discretization-of-each-plane), but before I try to go down that rat hole,

**Does anyone know (or wish to provide), a solution?**

```auto

fig = go.Figure(go.Scattermapbox(
    mode = "lines",
    lon = lons,
    lat = lats,
    marker = {'size': 10}))

fig.update_layout(
    margin ={'l':0,'t':0,'b':0,'r':0},
    mapbox = {
        'center': {'lon': 10, 'lat': 10},
        'style': "stamen-terrain",
        'center': {'lon': -20, 'lat': -20},
        'zoom': 1})
map2d = fig

```

Thanks!

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [March 18, 2020, 2:34am UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335/2 "2020-03-18T02:34:07Z")

</div>

@jonschull

You cannot draw a styled mapbox on the floor of a 3d plot. You can only plot the boundaries of a map

like in this plot: [https://plot.ly/~empet/14375https://plot.ly/~empet/14375](https://plot.ly/~empet/14375),  
reading a geojson file of the region of interest, and drawing the boundaries as `Scatter3d`, `mode='lines'` :

```auto
import json
import urllib.request
import numpy as np
import plotly.graph_objects as go

#Load and read the geojson file for your map

map_url = "https://raw.githubusercontent.com/openpolis/geojson-italy/master/geojson/limits_IT_regions.geojson" #here is a geojson file for Italy
with urllib.request.urlopen(map_url) as url:
        jdata = json.loads(url.read().decode())
              
pts = []#list of points defining boundaries of polygons
for feature in jdata['features']:
    if feature['geometry']['type'] == 'Polygon':
        pts.extend(feature['geometry']['coordinates'][0])    
        pts.append([None, None])#mark the end of a polygon   
        
    elif feature['geometry']['type'] == 'MultiPolygon':
        for polyg in feature['geometry']['coordinates']:
            pts.extend(polyg[0])
            pts.append([None, None])#end of polygon
    elif feature['geometry']['type'] == 'LineString': 
        points.extend(feature['geometry']['coordinates'])
        points.append([None, None])
    else: pass           
    #else: raise ValueError("geometry type irrelevant for map")
x, y = zip(*pts)    
h=0
z= h*np.ones(len(x))
fig = go.Figure()
fig.add_scatter3d(x=x, y=y, z=z, mode='lines', line_color='#999999', line_width=1.5)
fig.show()

```

---

<div class="post-metadata">

**Author:** ![jonschull](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jonschull/32/9202_2.png) [@jonschull](https://community.plotly.com/u/jonschull)\
**Post date:** [March 19, 2020, 4:41am UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335/3 "2020-03-19T04:41:13Z")

</div>

Perfect!

Thank you so much!

---

<div class="post-metadata">

**Author:** ![jonschull](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jonschull/32/9202_2.png) [@jonschull](https://community.plotly.com/u/jonschull)\
**Post date:** [March 19, 2020, 6:19am UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335/4 "2020-03-19T06:19:11Z")

</div>

Sorry to be dense, but would you mind sharing the python code you used for your example (in which one trace is lines, and the other is markers).?

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [March 19, 2020, 8:18am UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335/5 "2020-03-19T08:18:23Z")

</div>

@jonschull

After definning the `Scatter3d` trace of map boundaries I recorded positions to mark North, South, Est, West as follows:

```auto
xmin, xmax = np.nanmin(np.array(x, dtype=np.float)), np.nanmax(np.array(x, dtype=np.float))
ymin, ymax = np.nanmin(np.array(y, dtype=np.float)), np.nanmax(np.array(y, dtype=np.float))
N = [0.5*(xmin+xmax), ymax]
S = [0.5*(xmin+xmax), ymin]
W = [xmin, 0.5*(ymin+ymax)]
E = [xmax, 0.5*(ymin+ymax)]

```

and defined an associated trace:

```auto
NSEW = go.Scatter3d(
            x=[N[0], S[0], W[0], E[0]],
            y=[N[1], S[1], W[1], E[1]],
            z=[h]*4,
            mode='markers+text',
            marker=dict(size=0.5, color='rgb(230,230,230)'),
            text=['N', 'S', 'W', 'E'])

```

From a pandas DataFrame, df, with the columns ‘Region’, ‘Lon’, ‘Lat’, where for each index, Lon and Lat are geographical  
coordinates of the corresponding Region center, has been set up the Scatter3d trace for markers (`mode='markers'`):

```auto
marker_t = go.Scatter3d(
             x=df['Lon'],
             y=df['Lat'],
             z=[h]*len(df),
             mode='markers',
             marker=dict(size=4, color='blue'))

```

---

<div class="post-metadata">

**Author:** ![jonschull](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jonschull/32/9202_2.png) [@jonschull](https://community.plotly.com/u/jonschull)\
**Post date:** [March 19, 2020, 4:53pm UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335/6 "2020-03-19T16:53:52Z")

</div>

yes, and then how exactly do you marry that with with the other graph (in my hands, fig.add\_trace is producing an emtpy graph)

Thanks again(again)

---

<div class="post-metadata">

**Author:** ![jonschull](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jonschull/32/9202_2.png) [@jonschull](https://community.plotly.com/u/jonschull)\
**Post date:** [March 19, 2020, 5:02pm UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335/7 "2020-03-19T17:02:09Z")

</div>

never mind, got it:

fig=go.Figure()  
fig.add\_scatter3d(…)  
fig.add\_scatter3d(…)  
fig;

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [March 19, 2020, 5:24pm UTC](https://community.plotly.com/t/put-a-geographical-map-on-the-floor-of-a-scatter3d-to-track-coronavirus-infection-events/36335/8 "2020-03-19T17:24:14Z")

</div>

@jonschull

You can insert all traces as follows:

fig= go.Figure(data=[trace\_boundaries, NSEW, marker\_t])

If you fix h=0 (the floor level), then the following layout updates are recommended:

```auto
fig.update_layout(width=800, height=800) #you can tune these dims 
fig.update_scenes(xaxis_title= 'lon',
                  yaxis_title= 'lat',
                  zaxis_range=[h-0.01, H]) #H is the height of the third axis to be set by you

```
