Point color on deck_gl_chart ScatterplotLayer

Hey there

I’m having a hard time with deck gl chart, the examples work just fine but as soon as I try to do something slightly more complex I stumble into problems. The documentation is not a big help either. I understand that this is probably due to the fact that this is a wrapper around a js library.

Anyway, my extremely simple problem is, how do I set the color of the dots on a scatter plot based on the value of a column?

I tried several combinations including the getColorR/G/B property inside an encoding dictionary as described in the docs but with no luck. E.g.

      layers=[
          {
            "type": "ScatterplotLayer",
            "data": df,
            "encoding":{
              "getColor": "colorR"
            }
          }
      ],

Where colorR is an existing column on my df (tried with values from 0 to 1 and values from 0 to 255).

Can someone provide a working (even if simple) example?

Thank you in advance

Hi @Alexandre_Domingues ,

I also came across this issue. So far, here is the code I managed to get running to have multiples colors on my map :

layers=[  
        {
         'id': "scat-blue",
         'type': 'ScatterplotLayer',
         'data': data.iloc[:25],
         'opacity': 1,
         'getColor': [75,205,250],
         'pickable': True,
         'autoHighlight': True,
         'getRadius': 200,
         'radiusMinPixels': 5,
          },{
         'id': 'scat-red',
         'type': 'ScatterplotLayer',
         'data': data.iloc[25:50],
         'opacity': 1,
         'getColor': [255,94,87],
         'autoHighlight': True,
         'pickable': True,
         'getRadius': 200,
         'radiusMinPixels': 5,
         }
     ] 

I hope that helps :slight_smile:
Best,

1 Like

Thanks for your reply.
I was also able to add different colors to different data points by plotting them in separate layers, it should be possible to do it with a single layer.
I guess it will do for now :+1:

1 Like

A bit late to the party, but I found a solution to this. if the DataFrame contains three columns, each with ints from 0 to 255, they can be called in a color argument by column name in list format. If the columns are named e.g. ‘r’, ‘g’ and ‘b’, the call looks like so: ‘getColor’: [‘r’,‘g’,‘b’]

Then you can set the color of each point completely as you want in a single layer.

Minimal example using Streamlit:

import pandas as pd
import pydeck as pdk
import streamlit as st

df = pd.DataFrame(
   {
        'lat': [-16, -17, -18],
        'lon': [-60, -65, -70],
        'r': [255, 0, 0],
        'g': [0, 255, 0],
        'b': [0, 0, 255]
    }
)

st.pydeck_chart(
    pdk.Deck(
        map_style='mapbox://styles/mapbox/light-v9',
        initial_view_state=pdk.ViewState(
            latitude=-17,
            longitude=-65,
            zoom=4,
            pitch=50
        ),
        layers = [
            pdk.Layer(
                "ScatterplotLayer",
                df,
                get_position=['lon', 'lat'],
                get_fill_color=['r', 'g', 'b'],
                get_line_color=[0, 0, 0],
                get_radius=100000
            )
        ]
    )
)
1 Like

You can use a single column holding RGB triples as lists. Look at my example app here.

...

COLOUR_RANGE = [
    [29,53,87,220],
    [69,123,157,220],
    [168,218,220,220],
    [241,250,238,220],
    [239,35,60,220],
    [217,4,41,220]
]

....

max = mapdata.loc[:,'Value'].max(axis=0)
min = mapdata.loc[:,'Value'].min(axis=0)
mapdata.loc[:,'normValue'] = ((mapdata.loc[:,'Value'] / (max - min))*radius_unit*radius_scale)

# calculate colour range mapping index to then assign fill colour
mapdata.loc[:,'fillColorIndex'] = ( (mapdata.loc[:,'Value']-min) / (max-min) )*(len(COLOUR_RANGE) - 1)
mapdata.loc[:,'fill_color'] = mapdata.loc[:,'fillColorIndex'].map(lambda x: COLOUR_RANGE[int(x)])

scatterplot_layer = pdk.Layer(
    type='ScatterplotLayer',
    id='scatterplot-layer',
    data=mapdata,
    pickable=True,
    get_position=['longitude', 'latitude'],
    get_radius='normValue',
    radius_min_pixels=2*radius_scale,
    radius_max_pixels=30*radius_scale,
    get_fill_color='fill_color',
    get_line_color=[128,128,128, 200],
    get_line_width=4000,
    stroked=True,
    filled=True,
    opacity=opacity
)