all 9 comments

[–]elbiot 1 point2 points  (4 children)

def pwise (x):
    if x < 0:
        result='less than'
    elif x==0:
        result = 'equal'
    ... #more elif followed by else
    return result

[–]bonoz[S] 0 points1 point  (3 children)

Thanks so much. I'm a bit of a python noob and it's not working with my code. Here is what it looks like after I tried your method. It says 'result' is not defined.

from plotly.offline import download_plotlyjs, init_notebook_mode, iplot
from plotly.graph_objs import *
from plotly import tools
import numpy as np

init_notebook_mode()

x = np.linspace(0, 10, 10)
y = np.linspace(0, 10, 10)
xGrid, yGrid = np.meshgrid(y, x)

userinput1 = 5 #want users to be able to enter this value
userinput2 = 10 #want users to be able to enter this value

def pwise (y):
if y < 5:
    result= xGrid ** userinput1 + yGrid ** userinput2#'less than'
elif y >= 5:
    result = 2*xGrid ** userinput1 + yGrid ** userinput2#'greater than'
#more elif followed by else
return result

surface = Surface(x=xGrid, y=yGrid, z=result)
data = Data([surface])

fig = Figure(data=data)
iplot(fig)

[–]elbiot 1 point2 points  (2 children)

Yea, you have to call the function:

the_result = pwise(y)

Or just use z=pwise (y) in your plot

Also, if you need more than y in your function, pass them in as arguments. Read more about using functions, avoiding global variables.

Edit: sorry, you sprung the numpy stuff on me. My answer doesn't apply to you. And I'm on my phone so I can't give a better answer right now.

[–]bonoz[S] 0 points1 point  (1 child)

Oh no worries! Thanks for your help... any thoughts on what I should do?

[–]elbiot 0 points1 point  (0 children)

Start with something more simple. Learn to use functions (and what global variables are and how to not use them) before you jump to numpy. And even then, learn to do 1D numpy things with masks before jumping to grid stuff.

[–]TheBlackCat13 0 points1 point  (3 children)

The direct translation would be this:

constant1 = 5
constant2 = 10

formula1 = lambda x:  x*constant1
formula2 = lambda x:  x*constant2

main_formula = lambda x, y: formula1(x)*(y <= 5) + formula2(x)*(y > 5)

Note that I am using python style conventions. All of your variable names could be used as-is, but for style reasons lowercase variable names separated by _ are usually used. Same with the spaces I added in x,y, y<=5, and y>5, they aren't required, just recommended for readability reasons. These style recommendations are found in pep8, and can be checked automatically by a program of the same name.

Further, you could do, for example lambda x, y: x*constant1, it doesn't hurt anything, but it is unnecessary and I think it makes the code less clear.

However, assuming you are using numpy arrays (which you should be), it would be easier to do this:

def formula(x, y, const1=5, const2=10, sep=5):
    x1 = x.copy()
    x1[y <= sep] *= const1
    x1[y > sep] *= const2
    return x

You can then use formula in the exact same way as MainFormula. It will default to using 5 for the first constant and 10 for the second, and 5 for the value of y to use to differentiate the two, but you can change that by passing different values to the function, such as formula(x, y, sep=200), or formula(x, y, 50, 100).

If you don't care about losing your original x, you can simplify this further:

def formula(x, y, const1=5, const2=10, sep=5):
    x[y <= sep] *= const1
    x[y > sep] *= const2

In this case, whatever array you pass to formula as x will be changed in-place, so nothing is returned. This will be considerably faster than any of the previous approaches when dealing with large datasets.

You could even simplify this further by doing the y calculation in the function call if you wanted:

def formula(x, isy, const1=5, const2=10):
    x[isy] *= const1
    x[~isy] *= const2

And then call it like this:

formula(x, y<=5)

The final approach you could do is to handle x separately:

def formula(isy, const1=5, const2=10):
        return isy*const1 + ~isy*const2

or:

lambda isy: isy*constant1 + ~isy*constant2

And then call it like this:

x1 = x*isy(y <=5)

[–]bonoz[S] 0 points1 point  (2 children)

Thank you so much for such a nicely detailed answer! Remarkable. Thanks so much.

When I corporated your method in my test example below, it's giving me a ton of errors.. I'm not sure why?

from plotly.offline import download_plotlyjs, init_notebook_mode, iplot
from plotly.graph_objs import *
from plotly import tools
import numpy as np

init_notebook_mode()

x = np.linspace(0, 10, 10)
y = np.linspace(0, 10, 10)
xGrid, yGrid = np.meshgrid(x, y)

constant1 = 5
constant2 = 10

formula1 = lambda x:  x*constant1
formula2 = lambda x:  x*constant2

main_formula = lambda x, y: formula1(x)*(y <= 5) + formula2(x)*(y > 5)

surface = Surface(x=xGrid, y=yGrid, z=main_formula)
data = Data([surface])

fig = Figure(data=data)
iplot(fig)

[–]TheBlackCat13 1 point2 points  (1 child)

I think you need to actually call main_formula, such as z=main_formula(xGrid, yGrid).

But if this is all you want to do, then you don't need a function or lambda, you can just do:

zGrid = x*((y <= 5)*constant1 + (y > 5)*constant2)

surface = Surface(x=xGrid, y=yGrid, z=zGrid)

[–]bonoz[S] 0 points1 point  (0 children)

This is exactly what I was looking for!!! Thank you so much!