How to solve Invalid element(s) received for the 'color' property?

I have a piece of code that gives various colours to scatterplot dots based on the hour of the day wherein they were observed. This is done per this code:

color=listCoords.index.hour

In the contextual code:

return go.Figure(
        data=[
            # Data for all observations based on date and time
            Scattermapbox(
                lat=listCoords["Lat"],
                lon=listCoords["Lon"],
                mode="markers",
                hoverinfo="text + lat + lon",
                text=listCoords.index.hour,
                marker=dict(
                    showscale=True,
                    color=listCoords.index.hour,
                    opacity=np.where((listCoords['Threat'] == '3'), 0.1, 0.7), 
                    size=np.where((listCoords['Threat'] == '3'), 20, 7),
                    colorscale=[
                        [0, "#F4EC15"],
                        [0.04167, "#DAF017"],
                        [0.0833, "#BBEC19"],
                        [0.125, "#9DE81B"],
                        [0.1667, "#80E41D"],
                        [0.2083, "#66E01F"],
                        [0.25, "#4CDC20"],
                        [0.292, "#34D822"],
                        [0.333, "#24D249"],
                        [0.375, "#25D042"],
                        [0.4167, "#26CC58"],
                        [0.4583, "#28C86D"],
                        [0.50, "#29C481"],
                        [0.54167, "#2AC093"],
                        [0.5833, "#2BBCA4"],
                        [1.0, "#613099"],
                    ],
                    colorbar=dict(
                        title="Time of<br>Day",
                        x=0.93,
                        xpad=0,
                        nticks=24,
                        tickfont=dict(color="#d8d8d8"),
                        titlefont=dict(color="#d8d8d8"),
                        thicknessmode="pixels",
                    ),
                ),
            ),

I want to change ‘color=’ into:

color=np.where((listCoords['Threat'] == '3'), 'red', listCoords.index.hour)

so that the dots become ‘red’ if their ‘Threat’ value equals ‘3’
otherwise “color” should just be ‘listCoords.index.hour’

But this new code update gives:

ValueError: 
    Invalid element(s) received for the 'color' property of scattermapbox.marker
        Invalid elements include: ['4', '4', '4', '4', '4', '4', '4', '4', '4', '4']

    The 'color' property is a color and may be specified as:
      - A hex string (e.g. '#ff0000')
      - An rgb/rgba string (e.g. 'rgb(255,0,0)')
      - An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
      - An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
      - A named CSS color:
            aliceblue, antiquewhite, aqua, aquamarine, azure,
            beige, bisque, black, blanchedalmond, blue,
            blueviolet, brown, burlywood, cadetblue,
            chartreuse, chocolate, coral, cornflowerblue....

QUESTION: So yes, it is expecting a CSS color obviously. But seeing that initially ‘color=’ did consider listCoords.index.hour as
a value, how can I make this item consider that value again if not
‘red’?

@mirceau
The marker_color should be a list of numbers, not strings, i.e.:

marker_color= [2, 1, 3, 4, 1, 2, 3, 1]

or from the error message you have defined
marker_color= ['2', '1', '3', '4', '1', '2', '3', '1']

Hi @empet, Hmm strangely enough the individual items are all numbers not strings. Because if I do int(listCoords.index.hour) it says that it is expecting a string not an integer for the int() arg.

@miceau

Define:

marker_color= np.array(listlistCoords.index.hour).astype(int)

@empet, So if I do:

color=np.array(listCoords.index.hour).astype(int) it works.

but if I do:

color=np.where((listCoords['Threat'] == '3'), 'red', (np.array(listCoords.index.hour).astype(int)))

I get the same error:

ValueError: 
    Invalid element(s) received for the 'color' property of scattermapbox.marker
        Invalid elements include: ['4', '4', '4', '4', '4', '4', '4', '4', '4', '4']

    The 'color' property is a color and may be specified as:
      - A hex string (e.g. '#f....

Maybe I should use some other conditional-statement instead of np.where()

@mirceau

I do not understand this defintion:

color=np.where((listCoords['Threat'] == '3'), 'red', (np.array(listCoords.index.hour).astype(int)))

listCoords is a DataFrame?

Give a few elements in listCoords['Threat'] to see what is its relationship with red.

@empet, yes no problem:

listCoords is a DataFrame which consists of the date/time, lat, lon and Threat columns. Which together describe the sensor observations at a specific location. If they are observed near a specific area than they are assigned a threat level (1, 2 or 3 with 3 being the highest threat).

A print() outputs:

Date/Time             Lat                Lon                  Threat         
2019-06-02 04:00:00   -10.79789142125207  20.180154155730854      1
2019-06-02 04:05:00  -10.798373170162265  20.162651967016593      3

And for listCoords['Threat']=='3'

print() gives:

 listCoords: Date/Time
2019-06-02 04:00:00    False
2019-06-02 04:05:00    False
2019-06-02 04:10:00    False
2019-06-02 04:15:00    False
2019-06-02 04:20:00    False
                       ...  
2019-06-02 16:25:00    False
2019-06-02 16:30:00    False
2019-06-02 16:35:00    False
2019-06-02 16:40:00    False
2019-06-02 16:45:00    False
Name: Threat, Length: 241, dtype: bool

Now, If I have color=(np.array(listCoords.index.hour).astype(int)). Then each dot on the map gets an color according to the time it was observed in within a 24 hours day. So an observation at 8 a.m gets the color yellow/greenish. And an observation from 20:00 gets a more blue/purpleish color.

And if I have color=np.where((listCoords['Threat'] == '3'), 'red', 'blue')

Than this works as well and give everything a blue color and those records that have ‘threat’ ==‘3’ get red.

So no to make the overall picture work even better I combine the two ideas by saying:

np.where( *condition* [, *red* , *regular colours based on observations according to hour* ])

thus:

color=np.where((listCoords['Threat'] == '3'), 'red', (np.array(listCoords.index.hour).astype(int)))

Oh and (np.array(listCoords.index.hour).astype(int)) gives the output:

 [ 4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  5  5  5  5  5  5  5
  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  6  6  6  6  6  6  6
  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  7  7  7  7  7  7  7
  7  7  7  7  7  7  7  7  7  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8
  8  8  8  8  8  8  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9
  9  9  9  9 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 12 12 12 12
 12 12 12 12 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13
 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14
 14 14 14 14 14 14 14 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15
 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 16 16 16 16 16 16 16 16 16
 16]

which are the frequency of observations for every hour within 24 hours.

Hope this is clear

Before defining the Scattermapbox, try to get the right list of colors:

mycolors = np.where((listCoords['Threat'] == '3'), 'red', listCoords.index.hour)

print(mycolors)

if mycolors is a list of strings then insert in the Scattermapbox definition:

marker_color= np.array(mycolors).astype(int)

or marker_color = np.array(mycolors, int)

1 Like

print(mycolors) outputs:

['4' '4' '4' '4' '4' '4' '4' '4' '4' '4' '4' '4' '4' '4' '4' '4' '4' '5'
 '5' '5' '5' '5' '5' '5' '5' '5' '5' '5' '5' '5' '5' '5' '5' 'red' '5'
 'red' 'red' '5' '5' '5' 'red' 'red' 'red' '6' 'red' '6' 'red' '6' 'red'
 '6' 'red' '6' 'red' '6' 'red' 'red' '6' '6' 'red' '6' '6' '6' 'red' '6'
 'red' 'red' 'red' 'red' '7' 'red' 'red' 'red' '7' 'red' 'red' '7' 'red'
 'red' '7' 'red' 'red' '8' '8' '8' '8' '8' '8' 'red' '8' '8' 'red' '8'
 'red' '8' 'red' '8' 'red' 'red' '8' '8' '8' 'red' 'red' '9' 'red' 'red'
 '9' 'red' '9' '9' '9' '9' '9' '9' '9' '9' '9' '9' '9' '9' '9' '9' '9' '9'
 '10' '10' '10' '10' '10' '10' '10' '10' '10' '10' '11' '11' '11' '11'
 '11' '11' '12' '12' '12' '12' '12' 'red' 'red' 'red' 'red' '13' '13'
 'red' 'red' '13' 'red' 'red' 'red' 'red' '13' 'red' 'red' 'red' '13' '13'
 'red' '13' '13' '13' '14' '14' '14' '14' '14' '14' '14' '14' '14' '14'
 '14' '14' '14' '14' '14' '14' '14' '14' '14' '14' '14' '14' '14' '14'
 '14' '14' '14' '14' '14' 'red' '14' '15' '15' '15' '15' '15' '15' '15'
 '15' '15' '15' '15' '15' '15' 'red' '15' '15' '15' 'red' '15' 'red' 'red'
 '15' '15' '15' '15' '15' 'red' 'red' '15' '15' '15' 'red' 'red' 'red'
 'red' 'red' '16' '16' '16' '16' '16' '16']

Perhaps I should try to get the ‘red’ as a string and the numbers as non-strings. Because current color=np.array(mycolors).astype(int) gives

ValueError: invalid literal for int() with base 10: 'red'

@mirceau
Just assign a numerical code to ‘red’ .

1 Like

@empet, maybe a stupid question but do you mean like:

red = 99

or

red = #ff0000

Should I do this after print(mycolors) ?

Mircea, no!!! The second one is not a numerical value.

@empet, I got it working. (I secretly hope this is actually correct and not that it only seems correct)

First I altered the color_scale by saying that [0, “#FF0000”] (meaning equals red).
Then I just said that if ‘Threat == 3’ give 0 else give regular colours.

my new code (only parts that have changed):

red = 0
    mycolors = np.where((listCoords['Threat'] == '3'), red, listCoords.index.hour)
    print(mycolors)

and

color=np.array(mycolors, int),
                    colorscale=[
                        [0, "#FF0000"],
                        [0.04167, "#DAF017"],
                        [0.0833, "#BBEC19"],
                        [0.125, "#9DE81B"],
                        [0.1667, "#80E41D"],
                        [0.2083, "#66E01F"],
                        [0.25, "#4CDC20"],
                        [0.292, "#34D822"],
                        [0.333, "#24D249"],
                        [0.375, "#25D042"],
                        [0.4167, "#26CC58"],
                        [0.4583, "#28C86D"],
                        [0.50, "#29C481"],
                        [0.54167, "#2AC093"],
                        [0.5833, "#2BBCA4"],
                        [1.0, "#613099"],
                    ],