How do you use elif when defining a variable? - python

I'm trying to execute code like the following
y = 6
x = 7 if y/6 == 1 elif y/6 == 2 x = 5 else x = 4
Simply, it does not work. I'm not sure how to make elif statements fit into defining variables on one line.
I'm able to use else statements like the following
y = 6
x = 7 if y/6 == 1 else x = 4
I want to be able to set x to 7 if y/6 ==1, x to 5 if y/6 == 2 and x to 4 if neither of those are the case

Use chained ternary expressions:
>>> y = 6
>>> x = 7 if y/6 == 1 else 5 if y/6 == 2 else 4
>>> x
7
The way to read this is:
x = ((7) if y/6 == 1 else ((5) if y/6 == 2 else (4)))
i.e. each expr1 if pred else expr2 is itself an expression.

You only need x = ... once at the beginning. The rest of the expression is evaluated as a value that will be assigned to x. You don't need to mention x again.
x = 7 if y/6 == 1 else 5 if y/6 == 2 else 4
In general, the syntax is
var = value1 if condition1 else value2 if condition2 else value3

Related

Implement a loop that keeps the user entering the input until the condition is not met

Hey guys I hope you're doing well.
The problem I have is that my loop is not well defined, therefore the condition that I give it is not met. The print of the DataFrame that I implemented inside the while loop is not performed when the condition is not met.
This is the code I have so far. By implementing the while loop it stopped returning me the modified dataframe. As I said before, the loop is poorly constructed.
Dataframe content:
1 2 3 4 5 6 7 8 9
A 5 3 X X 7 X X X X
B 6 X X 1 9 5 X X X
C X 9 8 X X X X 6 X
D 8 X X X 6 X X X 3
E 4 X X 8 X 3 X X 1
F 7 X X X 2 X X X 6
G X 6 X X X X 2 8 X
H X X X 4 1 9 X X 5
I X X X X 8 X X 7 9
Code:
import pandas as pd
def modifyDF():
T = pd.read_fwf('file', header= None, names=['1','2','3','4','5','6','7','8','9'])
T = T.rename(index={0:'A',1:'B',2:'C',3:'D',4:'E',5:'F',6:'G',7:'H',8:'I'})
df = pd.DataFrame(T)
print(T,'\n')
x= input('row: ')
y= input('column: ')
v= input('value: ')
while 'X' in df:
f = df.loc[x,y]= v
print(f)
while 'X' not in df:
break
modifyDF()
Expected OUTPUT:
1 2 3 4 5 6 7 8 9
A 5 3 X X 7 X X X X
B 6 X X 1 9 5 X X X
C X 9 8 X X X X 6 X
D 8 X X X 6 X X X 3
E 4 X X 8 X 3 X X 1
F 7 X X X 2 X X X 6
G X 6 X X X X 2 8 X
H X X X 4 1 9 X X 5
I X X X X 8 X X 7 9
row: D #For example
column: 2 #For example
value: 1 #For example
#The modified dataframe:
1 2 3 4 5 6 7 8 9
A 5 3 X X 7 X X X X
B 6 X X 1 9 5 X X X
C X 9 8 X X X X 6 X
D 8 1 X X 6 X X X 3
E 4 X X 8 X 3 X X 1
F 7 X X X 2 X X X 6
G X 6 X X X X 2 8 X
H X X X 4 1 9 X X 5
I X X X X 8 X X 7 9
#The goal would be for this to run like a loop until there are no 'X' left in the dataframe.
I really appreciate your help :)
Generally speaking, you'd better not loop through a pandas DataFrame, but use more pythonic methods. In this case, you need to move your while loop a bit higher in your code, before the input statements, so your function would become:
def modifyDF():
T = pd.read_fwf('file', header=None, names=['1','2','3','4','5','6','7','8','9'])
T = T.rename(index={0:'A',1:'B',2:'C',3:'D',4:'E',5:'F',6:'G',7:'H',8:'I'})
df = pd.DataFrame(T)
print(T,'\n')
while df.isin(['X']).any().any():
x = input('row: ')
y = input('column: ')
v = input('value: ')
df.loc[x,y] = v
f = v
print(f)
Also remember that f = df.loc[x,y]= v is wrong in Python.

Printing Fibonacci Series having 2 similar codes but different outputs. Why?

Resolve CODE 2 to print output as CODE 1 and give the reason why both of the codes have different outputs.
Fibonacci Series
CODE 1
x = 0
y = 1
while x < 10:
print(x)
x, y = y, x + y
output
0
1
1
2
3
5
8
CODE 2
x = 0
y = 1
while x < 10:
print(x)
x = y
y = x + y
Output
0
1
2
4
8
Those are simply not identical.
In the first code block y becomes x+y and in the second code block y becomes 2*y.
Just a quick note the output of the second code block is 0 1 2 4 8 and not what you wrote (this was fixed).

Can't figure out what a loop with a binning lambda function does

This structure is part of a vastly larger project, but I can't seem to figure out how the lambda portion of this works:
for num in range(1,100):
dataframe[f'n{num}_bins'] = dataframe[f'n{num}'].apply(
lambda x: 0 if x < 1
else 1 if x < 2
else 2 if x < 3
else 3 if x < 4
else 4 if x < 5
else 5 if x < 6
else 6
What does lambda check for, exactly?
For each row (this is what apply does) in the f'n{num}' column (and for each such column, as per the outer loop):
if the value x at that location is smaller than:
1 -> return 0
2 -> return 1
...
6 -> return 5
otherwise (values >=6) -> return 6
Look into Does Python have a ternary conditional operator?
Convert the lambda function to normal function, you will know what's going on:
def func(x):
if x < 1:
return 0
elif x < 2:
return 1
elif x < 3:
return 2
elif x < 4:
return 3
elif x < 5:
return 4
elif x < 6:
return 5
else:
return 6
Generally, when you have so many conditions, using lambda is very unpythonic and is not recommended either.
You are confused with above lambda because it appears to be very ambiguous and unreadable.

For loop in pandas('transfer' solution from R to pandas)

I want to perform for loop in pandas: for each row i I want to take column x1 and perform the test(if else statements)
In R I will do like this:
df <- data.frame(x1 = rnorm(10),x2 = rexp(10))
for(i in 1:length(df$x1)){
if(df[i,'x1'] >0){
print('+')
} else{
print('-')
}
}
How can I do this in pandas data frame?
P.S I need to perfom a loop like this. But if you have better ideas, I will appreciate it
EDIT:
In case multiple comparison:
Thank you for the answer!
And maybe you can give me an advise, how can i do the iteration if i have multiple if/else statements? For example:
if x>0:
if x%2 == 0:
#do stuff 1
else:
#do other stuff 2
elif x<0:
if x%2 == 0:
#do stuff 3
else:
#do other stuff 4
If need new column use numpy.where:
np.random.seed(54)
df = pd.DataFrame({'x1':np.random.randint(10, size=10)}) - 5
df['new'] = np.where(df['x1'] > 0, '+', '-')
print (df)
x1 new
0 0 -
1 -3 -
2 2 +
3 -4 -
4 -5 -
5 3 +
6 2 +
7 -4 -
8 4 +
9 1 +
But if need loop (obviously avoid it, because slow) is possible use iteritems or items():
for i, x in df['x1'].iteritems():
if x > 0:
print ('+')
else:
print ('-')
EDIT:
df['new'] = np.where(df['x1'] > 0, 'a',
np.where(df['x1'] & 2, 'b', 'c'))
print (df)
x1 new
0 0 c
1 -3 c
2 2 a
3 -4 c
4 -5 b
5 3 a
6 2 a
7 -4 c
8 4 a
9 1 a
But if have many conditions (4 or more) use apply with custom function:
def f(x):
#x == 0
y = 5
if x>0:
if x%2 == 0:
y = 0
#do stuff 1
else:
y = 1
#do other stuff 2
elif x<0:
if x%2 == 0:
y = 2
#do stuff 3
else:
y = 3
#do other stuff 4
return y
df['new'] = df['x1'].apply(f)
print (df)
x1 new
0 0 5
1 -3 3
2 2 0
3 -4 2
4 -5 3
5 3 1
6 2 0
7 -4 2
8 4 0
9 1 1
You can use this code to print out each index with the correct symbol:
print(df['x1'].map(lambda x: '+' if x > 0 else '-').to_string(index=False))
What the above code does is creates a new Series object, for which you use the map function to convert each symbol into a + if i>0 and a - if i<=0. Then, the Series is converted to a string and printed out without indices.
But if you absolutely need to loop through each row, you can use the following code, which is what you have but condensed into 2 lines:
for i in df['x1']:
print('+' if i > 0 else '-')

Zero assignement in inline comparison

Example:
>>> x = 10
>>> x = x > 9 and 0 or x
>>> x
10
while:
>>> x = 10
>>> x = x > 9 and 1 or x
>>> x
1
Obviously 0 is treated as boolean False. How to use inline comparison to assign integer 0?
You probably want this
x= 0 if x > 9 else x
This is the python way of traditional ternary operators in c like languages.
The code snippet that you have will always give x or 1 for x > 9:
x = x > 9 and 0 or x
This is interpreted as
x = (x > 9 and 0) or x
x = 0 or x
x = x
The other version
x = x > 9 and 1 or x
is interpreted as
x = (x > 9 and 1) or x
x = 1 or x # or gets short-circuited so second expression is not evaluated
x = 1
try this:
x = 0 if x > 9 else x

Categories