Home > database >  if, and, elif all included within an apply(lambda x:
if, and, elif all included within an apply(lambda x:

Time:09-29

I have the below code:

data['ShortLongFlag'] = data['End DateTime'].apply(lambda x:
                                                   -1 if (x.month == 3 and x.date() in shortlongdates == True) else (1 if (x.month == 10 and x.date() in shortlongdates == True) else 0))

enter image description here

What I'm trying to do is the following:

Create a new column in my dataframe which is populated with either -1, 0 or 1 based on the following conditions:

  • -1 if the month of the value in my datetime column is equal to 3 and the date is in my list of dates called "shortlongdates"
  • 1 if the month of the value in my datetime column is equal to 10 and the date is in my list of dates called "shortlongdates"
  • 0 otherwise

Right now all the values are being outputted as 0 in the new column... why?

CodePudding user response:

The reason for this problem is chaining comparison operators

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

Comparisons, including membership tests and identity tests have same precedence.

i.e.

x.month == 3 and x.date() in shortlongdates == True

is same as

x.month == 3 and x.date() in shortlongdates and shortlongdates == True

Note that it can be written as x.month == 3 and x.date() in shortlongdates, or use brackets. However as already stated in comments this lambda is better written as regular function.

def replace_value(x):
    if x.date() in shortlongdates:
        return {3:-1, 10:1}.get(x.month, 0)
    return 0

I will leave up to you to convert this back to [simpler] lambda if you insist.

CodePudding user response:

So we have this unreadable thing:

lambda x: -1 if (x.month == 3 and x.date() in shortlongdates == True) else (1 if (x.month == 10 and x.date() in shortlongdates == True) else 0)

Let's write it out as a standard function:

def filterfn(x):
    if x.month == 3 and x.date() in shortlongdates:
        return -1
    elif x.month == 10 and x.date() in shortlongdates:
        return 1
    else:
        return 0

That removing some stranger tests (redundant == True) and brackets.

Is x.date() really a callable? Should it be x.date? Without seeing your data and listofdates it's impossible to say how this might fail, but at least we can see what it's doing.

  • Related