Ayush Ayush - 5 months ago 30
Python Question

Line comprehension in python

I want to write a small program that replaces certain values in an array with the desired value. The array (called "arr") contains about 10,000 elements of integer type and i would like to replace the digits 3,4 and 5 with 1.

I wrote the following code but it does not perform the desired function. Could someone help me figure out the logical error I am making. Thanks!

a=[1 if x==3|x==4|x==5 else x for x in arr]


Update:

My main objective was to write a function that gives values to summer, winter and shoulder months of the year and create a dataframe. The index is of datatime format. I was trying this line comprehension in the function as follows:

import pandas as pd

def season(df1):

df2=df1.copy()

arr=df2.index

arr=pd.to_datetime(arr)

arr=arr.month

######
# 300=summer,100=shoulder,200=winter

arr=pd.to_numeric(arr)

arr = [300 if x in {5,6,7,8} else x for x in arr]

arr = [100 if x in {3,4,9,10} else x for x in arr]

arr = [200 if x in {1,2,11,12} else x for x in arr]




df2["Value"]=arr

df2=df2[["Value"]]


return df2


It seems to do what is required in the function (I tried the step in my console and checked) but when i call it as a function it does not behave as expected and only the first line comprehension seems to work (I even tried changing the order, its the "300" value one that always works, rest are ignored). I cal the function as:

df_se=month.season(df_ot)


df_ot is another dataframe which i pick up the index from.

I am not able to understand if this weird behavior is due to the way i tried calling multiple line comprehensions or something is wrong with my logic (or both)

Thanks!

Answer

Logical OR is or, not |. | is bitwise OR. This list comprehension should be written as

a = [1 if x == 3 or x == 4 or x == 5 else x for x in arr]

or

a = [1 if x in (3, 4, 5) else x for x in arr]

Libraries like NumPy use | for broadcasted logical OR because or can't be overloaded, but even then, you generally need to parenthesize your comparisons to override the high precedence of |. If you're using NumPy, then instead of a list comprehension, you should do

a = np.where((arr == 3) | (arr == 4) | (arr == 5), 1, arr)