user9467747
user9467747

Reputation:

Mapping range of values to string

I have two different variables that can each have a different value between -1 and 1.

I want to be able to map each variable to their corrosponding string, based on their value being within a certain range, so for example:

var_a = 0.34
var_b = 0.94

# var_a ranges:

if var_a is between -0.1 and 0.1, then var_a = 'pink'
if var_a is between 0.1 and 0.35, then var_a = 'red'
...

# thus var_a = 'red'


# var_b ranges:

if var_b is between 0 and 1.0, then var_b = 'yellow'
if var_b is between -1.0 and -0.01, then var_b = 'lilac'
...

# thus var_b = 'yellow'

I have been able to do the above with if statements, but there's a large number of them and so it feels like there must be a better solution (trying to do this in Python).

Upvotes: 2

Views: 2997

Answers (4)

yyyyyyyan
yyyyyyyan

Reputation: 420

An alternative to the chain of ifs is working with a dictionary mapping functions (lambdas, if you might) to the values you want. So, using your example:

d = {(lambda x: -0.1 < x <= 0.1): 'pink', (lambda x: 0.1 < x <= 0.35): 'red'}
var_a = 0.2

for check in d:
    if check(var_a):
        var_a = d[check]
        break

This is nice if you're looking for a clean, concise and understandable solution.

Upvotes: 0

cs95
cs95

Reputation: 402333

You can do this really easily using the IntervalIndex API in pandas.

import pandas as pd

labels = ['pink', 'red']

idx = pd.IntervalIndex.from_breaks([-0.1, 0.1, 0.35], closed='left')
labels[idx.get_loc(0.34)]
# 'red'

Indexing is logarithmic time complexity for a given value (as opposed to all other solutions here, which are linear time). If you need to retrieve multiple indices, or if you need to handle out-of-bounds ranges, use idx.get_indexer.

Upvotes: 2

Ralf
Ralf

Reputation: 16495

One solution could be something like this:

def get_color(var_name, value):
    the_ranges = {
        'var_a': [
            (-0.1,  0.1 , 'pink'),
            ( 0.1,  0.35, 'red'),
        ],
        'var_b': [
            ( 0  ,  1.0 , 'yellow'),
            (-1.0, -0.01, 'lilac'),
        ],
    }

    for v_min, v_max, color in the_ranges[var_name]:
        if v_min <= value <= v_max:
            return color

    raise ValueError('nothing found for {} and value {}'.format(var_name, value))

This could be used like this:

>>> get_color('var_a', 0.34)
'pink'
>>> get_color('var_b', 0.94)
'yellow'

This has the advantage that the value ranges are (mostly) easy to read and all in one place (no if statements inbetween); This can be helpful when there are lots of variables and ranges to define.

Upvotes: 0

grapes
grapes

Reputation: 8636

This will work

ranges = {
    'red': (-1, 0),
    'blue': (0, 0.5),
    'pink': (0.5, 1),
}

var_x = 0.7

for name, range in ranges.items():
  if range[0] <= var_x <= range[1]:
    var_x = name
    break

print (var_x)

Upvotes: 4

Related Questions