Creating dictionary of lambda functions from pd.DataFrame

Viewed 34

I have a dummy_calcurve.csv file with parameters for a set of calibration curves as follows:

repeat,method,slope,intercept
a,linear,2,3
b,linear,4,5

I want to get a calcurve : dict of lambda-functions from this, such that I can calibrate for condition 'a' as follows: y=calcurve['a'](x).

I did the following:

calcurve = {}
ccs = pd.read_csv('dummy_calcurve.csv', index_col=0)
for repeat in ccs.index:
    slope = ccs.slope[repeat]
    intercept = ccs.intercept[repeat]
    print(repeat, slope, intercept)
    calcurve[repeat] = lambda x : slope * x + intercept
print(calcurve['a'](0))
print(calcurve['b'](0))
>>> a 2 3
>>> b 4 5
>>> 5
>>> 5

I would expect the final outputs to be 3 and 5. In other words, both calibration curves appear to be the second one (for b), while the intermediate print statements suggest otherwise.

What am I missing here?

1 Answers

EDIT 1

When adding the following, it works as expected.

def calibration(slope, intercept):
    return lambda x : slope * x + intercept

calcurve = {}
ccs = pd.read_csv('dummy_calcurve.csv', index_col=0)
for repeat in ccs.index:
    slope = ccs.slope[repeat]
    intercept = ccs.intercept[repeat]
    print(repeat, slope, intercept)
    calcurve[repeat] = calibration(slope, intercept)
>>> print(calcurve['a'](0))
>>> print(calcurve['b'](0))
>>> a 2 3
>>> b 4 5
>>> 3
>>> 5

I do not understand why this makes any difference.

EDIT 2 The following also fixes the issue.

calcurve = {}
ccs = pd.read_csv('dummy_calcurve.csv', index_col=0)
for repeat in ccs.index:
    slope = ccs.slope[repeat]
    intercept = ccs.intercept[repeat]
    print(repeat, slope, intercept)
    calcurve[repeat] = lambda x, s=slope, i=intercept : s * x + i
print(calcurve['a'](0))
print(calcurve['b'](0))

>>> a 2 3
>>> b 4 5
>>> 3
>>> 5

According to the official Python docs, this is global/local scope issue. The slope and intercept parameters are not local to the lambda and thus are being updated everywhere during every loop. By making an extra variable i and s, these do become local. For the same reason, adding another layer with the calibration-function, which makes the slope and intercept local as well, fixes the issue as well.

Related