Lambda Function in List Comprehensions

Lambda function in list comprehensions

The first one creates a single lambda function and calls it ten times.

The second one doesn't call the function. It creates 10 different lambda functions. It puts all of those in a list. To make it equivalent to the first you need:

[(lambda x: x*x)(x) for x in range(10)]

Or better yet:

[x*x for x in range(10)]

List comprehension with lambda function

This is because of Pythons late binding closures. You can fix the issue by writing:

def multipliers():
return [lambda x, i=i : i * x for i in range(4)]

List comprehension vs. lambda + filter

It is strange how much beauty varies for different people. I find the list comprehension much clearer than filter+lambda, but use whichever you find easier.

There are two things that may slow down your use of filter.

The first is the function call overhead: as soon as you use a Python function (whether created by def or lambda) it is likely that filter will be slower than the list comprehension. It almost certainly is not enough to matter, and you shouldn't think much about performance until you've timed your code and found it to be a bottleneck, but the difference will be there.

The other overhead that might apply is that the lambda is being forced to access a scoped variable (value). That is slower than accessing a local variable and in Python 2.x the list comprehension only accesses local variables. If you are using Python 3.x the list comprehension runs in a separate function so it will also be accessing value through a closure and this difference won't apply.

The other option to consider is to use a generator instead of a list comprehension:

def filterbyvalue(seq, value):
for el in seq:
if el.attribute==value: yield el

Then in your main code (which is where readability really matters) you've replaced both list comprehension and filter with a hopefully meaningful function name.

List comprehension and lambdas in Python

The y in your lambda refers to the last value that y had in the scope it came from, i.e., 9.

The easiest way to get the behavior you want is to use a default argument in your lambda:

lambda x, y=y: x/y

This captures the value of y at the moment the lambda function is defined.

You can also do a "double-lambda", calling a function that returns the lambda you want, passing in the desired value of y:

(lambda y: lambda x: x/y)(y)

Here, the outer lambda provides a new scope each time you call it.

Issues with list comprehension in Lambda function

You are using an expression (lambdas can only hold an expression), and so must use a conditional expression. Expressions always produce an object, so conditional expressions must have a true expression and a false expression, in the form

<true> if <condition> else <false>`

You left out the else <false> part.

You are making three additional mistakes:

  • You are treating a single column as a list of lists
  • You are appending whether or not your test is true
  • You are appending a list to a list, where you wanted to append a string instead.

Your test should just see if both elements are in the list; you can use set operations; you want to know if {1, 2} is a subset of the column values:

{1, 2}.issubset(row['list_1'])

and only then append something to the other column, so you want to execute row['list_2'].append() only if the above is true. And you want to append a single string, so call .append('test').

For the else part, you could return None, so not make an append call:

row['list_2'].append('test') if {1, 2}.issubset(row['list_1']) else None

or, in situ in the df.apply() call:

df.apply(lambda row: row['list_2'].append('test') if {1, 2}.issubset(row['list_1']) else None)

However, it would be better if you used the apply() only to return a boolean value, so you can select your rows with it, then use a separate action to append to the selected rows:

test = df.list_1.apply(lambda c: {1, 2}.issubset(c))
df.list_2[test].apply(lambda c: c.append('test'))

Here, test holds a series of boolean False and True values, corresponding with the rows where list_1 values are a superset of {1, 2}. That series can be used to select rows in df.list_2, where you can do other operations, including appending to the list objects in each cell.

It's a whole lot more readable, and easier to change if you wanted to switch from appending to nested list objects to just assigning a different value; e.g. setting the df.outcome column to 'tested' when the subset test passes, or to 'failed' if not, using numpy.where():

test = df.list_1.apply(lambda c: {1, 2}.issubset(c))
df.outcome = np.where(test, 'tested', 'failed')

Using list comprehension within lambda function?

Thanks to the comment by rdas, the solution was simply using hard brackets:

data['n_grams'] = data.n_grams.apply(lambda row: [" ".join(x) for x in row])

List comprehension instead of lambda in DataFrame.apply()?

What about

G['year'] = ["'{:02d}".format(x % 100) for x in G.year]

?



Related Topics



Leave a reply



Submit