Python mathematical expression evaluation - python

I was trying to solve a random problem, I used a relation that I made, when I've come to implement it in python it give me different results than the one that I calculated, so I tried to change.
the thing is I don't get how does python see each one!!?
those two expressions here give different results sometimes:
((column+1)//2) * ((row+1)//2)
= (column+1)//2 * (row+1)//2
Here's an example:
rows, columns = 4, 4
for row in range(2, rows+1):
for column in range(1, columns+1):
print('*'*15)
result = ((column+1)//2) * ((row+1)//2)
f_result = (column+1)//2 * (row+1)//2
print('>> normal expression:', (column+1)//2, (row+1)//2)
print('>> second expression:', ((column+1)//2), ((row+1)//2))
print('>> row:', row)
print('>> column:', column)
print('>> Results:', result, f_result)
print()
The last two entries in the results:
***************
>> normal expression: 2 2
>> second expression: 2 2
>> row: 4
>> column: 3
>> Results: 4 5
***************
>> normal expression: 2 2
>> second expression: 2 2
>> row: 4
>> column: 4
>> Results: 4 5

You need to understand operator precedence first
Check out this link
Now for the expression
((col+1)//2) * ((row+1)//2) = (col+1)//2 * (row+1)//2
((col+1)//2) * ((row+1)//2) = ((4+1)//2) * ((4+1)//2)
= (5//2)*(5//2)
= 2 * 2
= 4
(col+1)//2 * (row+1)//2 = (4+1)//2 * (4+1)//2
= 5//2 * 5//2
= 2 * 5//2
= 10//2 (as * has higher precedence over //)
= 5

Related

How extract specific number pattern from a list inside column of pandas dataframe

I have data frame like below to which I need to following transformations
Extract and keep only 3 decimals from first number before comma , and also keep only 3 decimal points for second number .
Comma should replaced by :
If the number has only two decimal points and add one zero extra to make it 3 decimal points.
Input
df
[151.20732,-33.86785]
[81.67732,-09.86]
[1.2890,43.8]
[567.200,33.867]
[557.21,33.86]
Expected Output
151.207:-33.867
81.677:-09.860
1.289:43.800
567.200:33.867
557.210,33.860
How can this be done in pandas?
This is hard than I thought
def func(y,n):
if y < 0 :
return "%0.3f" % (-(y * 10 ** n // -1 / 10 ** n))
else :
return "%0.3f" % (y * 10 ** n // 1 / 10 ** n)
df.apply(lambda x : ':'.join([ func (y, 3) for y in x]) )
Out[86]:
0 151.207:33.867
1 81.677:9.860
2 1.289:43.800
3 567.200:33.867
4 557.210:33.860
dtype: object
Input
data = [[151.20732,-33.86785],
[81.67732,-09.86],
[1.2890,43.8],
[567.200,33.867],
[557.21,33.86]]
df = pd.Series(data)
DataFrame Input Option 1:
data = [[[151.20732,-33.86785]],
[[81.67732,-09.86]],
[[1.2890,43.8]],
[[567.200,33.867]],
[[557.21,33.86]]]
df = pd.DataFrame(data, columns=['geo'])
DataFrame Input Option 2:
literal_eval is used to read a CSV file that contains a list, otherwise list is read as a single string.
import ast
literal = lambda x: ast.literal_eval(x)
data = pd.read_csv('/Test_data.csv', converters={'geo.geometry.coordinates': literal})
df = pd.DataFrame(data, columns=['geo.geometry.coordinates'])
df.rename(columns = {'geo.geometry.coordinates':'geo'}, inplace = True)
Algorithm:
import math
def trunc(f,d):
# Truncate float (f) to d decimal places, unless NaN
return 'nan' if math.isnan(f) else f"{int(f*10**d)/10**d:0.{d}f}"
df['geo_neo'] = df.apply(lambda r: trunc(r['geo'][0], 3) + ':'
+ trunc(r['geo'][1], 3), axis = 1)
DataFrame Output:
geo geo_neo
0 [151.20732, -33.86785] 151.207:-33.867
1 [81.67732, -9.86] 81.677:-9.860
2 [1.289, 43.8] 1.289:43.800
3 [567.2, 33.867] 567.200:33.867
4 [557.21, 33.86] 557.210:33.860

How to dynamically create columns based on multiple conditions

So I'm having the following problem:
I have a dataframe like the one bellow where time_diff_float is the time difference between each row and the row above in minutes. So, for example, I had value = 4 20 minutes after value = 1.
value | time_diff_float
1 NaN
4 20
3 13
2 55
5 08
7 15
First I have to check if the time difference between two rows is < 60 (one hour) and create a column using the formula rem = value (from row above) * lambda ** time difference between 2 rows . My lambda is a constant with the value of 0.97.
And then, if the time difference between each row and 2 rows above is still inferior to 60, I have to re-do the same thing comparing each row with 2 rows above. And then I have to do the same thing comparing 3 rows above and etc.
To do that I wrote the following code:
df.loc[df['time_diff_float'] < 60, 'rem_1'] = df['value'].shift() * (lambda_ ** (df['time_diff_float'] - 1))
df.loc[df['time_diff_float'] + df['time_diff_float'].shift() < 60, 'rem_2'] = df['value'].shift(2) * (lambda_ ** (df['time_diff_float'] + df['time_diff_float'].shift() - 1))
df.loc[df['time_diff_float'] + df['time_diff_float'].shift() + df['time_diff_float'].shift(2) < 60, 'rem_3'] = df['value'].shift(3) * (lambda_ ** (df['time_diff_float'] + df['time_diff_float'].shift() + df['time_diff_float'].shift(2) - 1))
My question is: since I have to re-do this at least 10 times (even more) with the real values I have, is there a way to create the "rem columns" dynamically?
Thanks in advance!
You can save a mask of your data and then update it in every time of the loop:
n = 3
for i in range(1, n):
if (i==1):
mask = df['time_diff_float']
df.loc[mask, 'rem_' +str(i)] = df['value'].shift() * (lambda_ ** (mask - 1))
else:
mask += df['time_diff_float'].shift(i-1)
df.loc[mask < 60, 'rem_'+str(i)] = df['value'].shift(i) * (lambda_ ** (mask - 1))

How exactly do the shortcut operators work in python?

I started learning python and while i was checking some of the examples about shortcut operators I ran into this one
a = 6
b = 3
a /= 2 * b
print(a)
which print 1.0 as the result which i'm sure is wrong because it's supposed to be the simplified version of:
a = a / 2 * b
which gives 9.0 as the result and I think makes more sense acording to the order
a /= <anything here> computes all of the <anything here> first, and then does the division and assignment. So in your example, it is equivalent to a = a / (2 * b) (note parentheses).
Think about how the order of operations works:
a /= c
Is equivalent to
a = a / c
In a similar line,
a /= 2 * b
Is tantamount to
a = a / (2 * b)
Which equates to 6 / (2 * 3) which indeed equals 1.
a /= 2 * b
is in other words a = a / ( 2 * b)
This
a /= 2 * b
corresponds to
a = a / (2 * b)
and not to
a / 2 * b

When I convert an expression using shortcut operators the output is wrong

I read that if I have the following expression:
variable = variable op expression
It can be simplified and shown as follows:
variable op= expression
For example: i = i + 2 * j --> i += 2 * j
However, I have used the previous example in a = a / 2 * b --> a /= 2 * b
Let a=6 and b=3. Using both values in a=a/2*b, the output is 9. However, in the case of a /= 2* b, the output is 1
This is because you are changing the order of operations.
a = a / 2 * b is interpreted as "Divide a by 2, then multiply by b, then store the result in a", or a = (a / 2) * b.
a /= 2 * b is interpreted as "Multiply 2 by b, then divide a by the result, and store the final result in a", or a = a / (2 * b).
I hope this helps.

How to multiply arrays in pandas?

I have two arrays
x = [a,b,c]
y = [5,6,7]
I want to calculate the product such that the result of x * y is
x[0]* 5 + x[1] * 6 + x[2] * 7
Actually this is part of constraints equation that I have to form for optimization using scipy and pandas.
Also,
I have many numpy arrays that I created after reading a csv file. And I want to create my objective function on run time.
Here is the hard coded form of the objective function
def objFunc(x,sign=1.0) :
"""return sign*(sum(coeff[0:] *(wf[0:] + wv[0:] * decisionVars[0:])**power.values[0:]))"""
return sign* (( coeff.values[0]*(wf.values[0]+ wv.values[0] *x[0])**power.values[0] ) +
(coeff.values[1]*(wf.values[1]+ wv.values[1] *x[0])**power.values[1])+
(coeff.values[2]*(wf.values[2]+ wv.values[2] *x[0])**power.values[2]) +
(coeff.values[3]*(wf.values[3]+ wv.values[3] *x[0])**power.values[3]) +
(coeff.values[4]*(wf.values[4]+ wv.values[4] *x[0])**power.values[4] )+
(coeff.values[5]*(wf.values[5]+ wv.values[5] *x[0])**power.values[5]) +
(coeff.values[6]*(wf.values[6]+ wv.values[6] *x[1])**power.values[6]) +
(coeff.values[7]*(wf.values[7]+ wv.values[7] *x[1])**power.values[7]) +
(coeff.values[8]*(wf.values[8]+ wv.values[8] *x[1])**power.values[8]) +
(coeff.values[9]*(wf.values[9]+ wv.values[9] *x[2])**power.values[9]) +
(coeff.values[10]*(wf.values[10]+ wv.values[10] *x[2])**power.values[10]) +
(coeff.values[11]*(wf.values[11]+ wv.values[11] *x[2])**power.values[11]))
I used various ways to calculate it but to no avail.
df = pd.DataFrame.from_csv('C:\Users\prashant.mudgal\Downloads\T1 - Copy.csv')
df2 = pd.DataFrame.from_csv('C:\Users\prashant.mudgal\Downloads\T2.csv')
decisionVars= df2['DV']
coeff = df2['coef']
"""subset for power"""
power = df2['p']
wf = df2['weight_f']
wv = df2['weight_v']
def objFunc(x,sign=1.0) :
return sign*(sum(coeff[0:] *(wf[0:] + wv[0:] * decisionVars[0:])**power.values[0:]))
This works out of the box:
In [9]: df = pd.DataFrame([[1,5],[2,6],[3,7]], columns=list('ab'))
In [10]: df
Out[10]:
a b
0 1 5
1 2 6
2 3 7
In [11]: df.a * df.b
Out[11]:
0 5
1 12
2 21
dtype: int64

Categories

Resources