Convert Cartesian expression to polar expression using SymPy - python-3.x

Is there a way to convert a Cartesian expression in SymPy to a polar one?
I have the following expression:
1/sqrt(x^2+y^2)
However, I can't seem to get SymPy to acknowledge that this is 1/r in polar coordinates. I tried using the 'subs' command, both of the following options (I imported sympy as asp, and defined all of the symbols earlier):
expr = 1/sp.sqrt(x**2+y**2)
expr.subs((x,y),(r*cos(theta),r*sin(theta))
expr.subs((sp.sqrt(x**2+y**2),sp.atan(y/x)),(r,theta))
but in both cases, I simply receive the original expr again.
Is there a way to convert a Cartesian expression to a polar one in SymPy?

subs((x,y),(r*cos(theta),r*sin(theta))
is not a correct syntax for subs. When multiple symbols are to be replaced, one has to provide either a dictionary
subs({x: r*sp.cos(theta), y: r*sp.sin(theta)})
or an iterable with pairs (old, new) in it:
subs(((x, r*sp.cos(theta)), (y, r*sp.sin(theta))))
The former is more readable; the latter is needed when substitutions must be carried out in a particular order (not the case here).
Either way, to achieve 1/r you also need to declare r as nonnegative
r = sp.symbols('r', nonnegative=True)
and simplify the result of substitution:
expr.subs({x: r*sp.cos(theta), y: r*sp.sin(theta)}).simplify()

Related

Sympy Error - Cant convert expression to float

I am trying to use SymPy to solve for the variable p by defining the function as shown.
On execution, an error " can't convert expression to float" is being raised. I have just started learning Python so I will really appreciate if someone can help me understand what's causing the error and suggest a way to fix it and solve for p.
Note- For the assigned vales of G, F and h, p= 91.65
Thanks!
G=0.05
F=0.32
h=231 # these values should yield p = 91.65
def get_p (G,F,h):
p = symbols('p')
C2 = 3.14 * h * F*F
C1= 3.14 * G *h
eq_p=Eq(p *(1/math.cosh(p/C1))**2 - C1* (math.tanh(p/C1))+C2==0) #raises the error "cant convert expression to float"
sol_p=solve(eq_p)
return sol_p
p= get_p (G, F, h)
print(p)
When you get an error like this and have no idea why it is happening use an interactive session to work with smaller and smaller parts of the offending line until the problem is located. In your case the issue is that math.cosh and math.tanh expect numeric arguments and you are giving it something with a SymPy symbol p. Fortunately, Sympy has its own hyperbolic functions. So, remove the 'math.' and then at the top use:
>>> from sympy import cosh, tanh
But another problem will become apparent: the Eq argument looks like 'expr==0' and it should be 'expr, 0' since args of Eq are the L and R in L == R: it should be in the form of Eq(L, R).
Finally, check your expression with print(eq_p.subs(p, 91.65))...it doesn't appear to be close to zero (and a plot of the function confirms that it does not go through 0). So you have perhaps interpreted the original expression you are trying to solve incorrectly in writing it here.
Once you have the right equation then I would recommend using nsolve(eq_p, guess) where guess is an approximate value of the solution for p. You can import that with from sympy import nsolve.

Trying to understand Julia syntax in linear regression code (GLM package)

Total Julia noob here (with basic knowledge of Python). I am trying to do linear regression and things I read suggest the GLM package. Here is some sample code I found here:
using DataFrames, GLM
y = 1:10
df = DataFrame(y = y, x1 = y.^2, x2 = y.^3)
sm = GLM.lm( #formula(y ~ x1 + x2), df )
coef(sm)
Can someone explain the syntax here? What does #formula mean? Docs here say #foo means a
macro which I guess is basically just a function, but where do I find the function/macro formula? Just looking at the use here though, I would have thought it is maybe passing y ~ x1 + x2 (whatever that is) as the formula argument to lm? (similar to keyword arguments = in python?)
Next, what is ~ here? General docs say ~ means negation but I'm not seeing how that makes here.
Is there a place in the GLM docs where all of this is explained? I'm not seeing that. Only seeing a few examples but not a full breakdown of each function and all of its arguments.
You have stumbled upon the #formula language that is defined in the StatsModels.jl package and implemented in many statistics/econometrics related packages across the Julia ecosystem.
As you say, #formula is a macro, which transforms the expression given to it (here y ~ x1 + x2) into some other Julia expression. If you want to find out what happens when a macro gets called in Julia - which I admit can often look like magic to new (and sometimes experienced!) users - the #macroexpand macro can help you. In this case:
julia> #macroexpand #formula(y ~ x1 + x2)
:(StatsModels.Term(:y) ~ StatsModels.Term(:x1) + StatsModels.Term(:x2))
The result above is the expression constructed by the #formula macro. We see that the variables in our formula macro are transformed into StatsModels.Term objects. If we were to use StatsModels directly, we could construct this ourselves by doing:
julia> Term(:y) ~ Term(:x1) + Term(:x2)
FormulaTerm
Response:
y(unknown)
Predictors:
x1(unknown)
x2(unknown)
julia> (Term(:y) ~ Term(:x1) + Term(:x2)) == #formula(y ~ x1 + x2)
true
Now what is going on with ~, which as you say can be used for negation in Julia? What has happened here is that StatsModels has defined methods for ~ (which in Julia is and infix operator, that means essentially it is a function that can be written in between its arguments rather than having to be called with its arguments in brackets:
julia> (Term(:y) ~ Term(:x)) == ~(Term(:y), Term(:x))
true
So writing y::Term ~ x::Term is the same as calling ~(y::Term, x::Term), and this method for calling ~ with terms on the left and right hand side is defined by StatsModels (see method no. 6 below):
julia> methods(~)
# 6 methods for generic function "~":
[1] ~(x::BigInt) in Base.GMP at gmp.jl:542
[2] ~(::Missing) in Base at missing.jl:100
[3] ~(x::Bool) in Base at bool.jl:39
[4] ~(x::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) in Base at int.jl:254
[5] ~(n::Integer) in Base at int.jl:138
[6] ~(lhs::Union{AbstractTerm, Tuple{Vararg{AbstractTerm,N}} where N}, rhs::Union{AbstractTerm, Tuple{Vararg{AbstractTerm,N}} where N}) in StatsModels at /home/nils/.julia/packages/StatsModels/pMxlJ/src/terms.jl:397
Note that you also find the general negation meaning here (method 3 above, which defines the behaviour for calling ~ on a boolean argument and is in Base Julia).
I agree that the GLM.jl docs maybe aren't the most comprehensive in the world, but one of the reasons for that is that the whole machinery behind #formula actually isn't a GLM.jl thing - so do check out the StatsModels docs linked above which are quite good I think.

TypeError: append() missing 1 required positional argument: 'values'

I have variable 'x_data' sized 360x190, I am trying to select particular rows of data.
x_data_train = []
x_data_train = np.append([x_data_train,
x_data[0:20,:],
x_data[46:65,:],
x_data[91:110,:],
x_data[136:155,:],
x_data[181:200,:],
x_data[226:245,:],
x_data[271:290,:],
x_data[316:335,:]],axis = 0)
I get the following error :
TypeError: append() missing 1 required positional argument: 'values'
where did I go wrong ?
If I am using
x_data_train = []
x_data_train.append(x_data[0:20,:])
x_data_train.append(x_data[46:65,:])
x_data_train.append(x_data[91:110,:])
x_data_train.append(x_data[136:155,:])
x_data_train.append(x_data[181:200,:])
x_data_train.append(x_data[226:245,:])
x_data_train.append(x_data[271:290,:])
x_data_train.append(x_data[316:335,:])
the size of the output is 8 instead of 160 rows.
Update:
In matlab, I will load the text file and x_data will be variable having 360 rows and 190 columns.
If I want to select 1 to 20 , 46 to 65, ... rows of data , I simply give
x_data_train = xdata([1:20,46:65,91:110,136:155,181:200,226:245,271:290,316:335], :);
the resulting x_data_train will be the array of my desired.
How can do that in python because it results array of 8 subsets of array for 20*192 each, but I want it to be one array 160*192
Short version: the most idiomatic and fastest way to do what you want in python is this (assuming x_data is a numpy array):
x_data_train = np.vstack([x_data[0:20,:],
x_data[46:65,:],
x_data[91:110,:],
x_data[136:155,:],
x_data[181:200,:],
x_data[226:245,:],
x_data[271:290,:],
x_data[316:335,:]])
This can be shortened (but made very slightly slower) by doing:
xdata[np.r_[0:20,46:65,91:110,136:155,181:200,226:245,271:290,316:335], :]
For your case where you have a lot of indices I think it helps readability, but in cases where there are fewer indices I would use the first approach.
Long version:
There are several different issues at play here.
First, in python, [] makes a list, not an array like in MATLAB. Lists are more like 1D cell arrays. They can hold any data type, including other lists, but they cannot have multiple dimensions. The equivalent of MATLAB matrices in Python are numpy arrays, which are created using np.array.
Second, [x, y] in Python always creates a list where the first element is x and the second element is y. In MATLAB [x, y] can do one of several completely different things depending on what x and y are. In your case, you want to concatenate. In Python, you need to explicitly concatenate. For two lists, there are several ways to do that. The simplest is using x += y, which modifies x in-place by putting the contents of y at the end. You can combine multiple lists by doing something like x += y + z + w. If you want to keep x, unchanged, you can assign to a new variable using something like z = x + y. Finally, you can use x.extend(y), which is roughly equivalent to x += y but works with some data types besides lists.
For numpy arrays, you need to use a slightly different approach. While Python lists can be modified in-place, strictly speaking neither MATLAB matrices nor numpy arrays can be. MATLAB pretends to allow this, but it is really creating a new matrix behind-the-scenes (which is why you get a warning if you try to resize a matrix in a loop). Numpy requires you to be more explicit about creating a new array. The simplest approach is to use np.hstack, which concatenates two arrays horizontally (or np.vstack or np.dstack for vertical and depth concatenation, respectively). So you could do z = np.hstack([v, w, x, y]). There is an append method and function in numpy, but it almost never works in practice so don't use it (it requires careful memory management that is more trouble than it is worth).
Third, what append does is to create one new element in the target list, and put whatever variable append is called with in that element. So if you do x.append([1,2,3]), it adds one new element to the end of list x containing the list [1,2,3]. It would be more like x = [x, {{1,2,3}}}, where x is a cell array.
Fourth, Python makes heavy use of "methods", which are basically functions attached to data (it is a bit more complicated than that in practice, but those complexities aren't really relevant here). Recent versions of MATLAB has added them as well, but they aren't really integrated into MATLAB data types like they are in Python. So where in MATLAB you would usually use sum(x), for numpy arrays you would use x.sum(). In this case, assuming you were doing appending (which you aren't) you wouldn't use the np.append(x, y), you would use x.append(y).
Finally, in MATLAB x:y creates a matrix of values from x to y. In Python, however, it creates a "slice", which doesn't actually contain all the values and so can be processed much more quickly by lists and numpy arrays. However, you can't really work with multiple slices like you do in your example (nor does it make sense to because slices in numpy don't make copies like they do in MATLAB, while using multiple indexes does make a copy). You can get something close to what you have in MATLAB using np.r_, which creates a numpy array based on indexes and slices. So to reproduce your example in numpy, where xdata is a numpy array, you can do xdata[np.r_[1:20,46:65,91:110,136:155,181:200,226:245,271:290,316:335], :]
More information on x_data and np might be needed to solve this but...
First: You're creating 2 copies of the same list: np and x_data_train
Second: Your indexes on x_data are strange
Third: You're passing 3 objects to append() when it only accepts 2.
I'm pretty sure revisiting your indexes on x_data will be where you solve the current error, but it will result in another error related to passing 2 values to append.
And I'm also sure you want
x_data_train.append(object)
not
x_data_train = np.append(object)
and you may actually want
x_data_train.extend([objects])
More on append vs extend here: append vs. extend

How does variable name scoping in Maxima work?

I am trying to plot a function test(a) which returns the root of another (in this case x^3-2*x^2+a):
Why does this not work? Why does it work when I change a to x in the last line?
The problem is that mnewton requires an expression which evaluates to a number after assigning values to the specified variables (just x in the example). To make this work, you need to prevent mnewton from being called until a has a value. For example, something like:
plot2d (lambda ([a], rhs(mnewton(p(x, a) = 0, x, 20)[1][1])), [a, -1, 1]);
where p(x, a) is the polynomial expression.
I've made the range of a smaller, since I get an error from mnewton for larger values of a.
You can also try find_root to solve equations of 1 variable.
Since the function is question is a cubic polynomial, there is an exact solution and Maxima can find it via: algsys([p(x, a)], [x]);

how to convert string into math expression in R?

I have a vectors of strings, say c("E^A","S^P","lambda","T","E^Q","E^Q","AT"), and I want to plot them as the x axis label using math expression. (I believe I have written them in math expression format, but with quote)
When I put
text(x,par("usr")[3]-0.2,labels=substitute(A,list(A=label)),srt=20,pos=1,adj = c(1.1,1.1), xpd = TRUE,cex=0.7)
The x axis only shows "E^A","S^P","lambda","T","E^Q","E^Q","AT", not the mathematical interpretation of the strings, and I guess it's because they are not regarded as math symbols.
How can I get mathematical labeling then? Thanks so much!
In general, use expression (see ?plotMath):
plot(1,main=expression(E^A))
Note that the 'E^A' is not in quote marks.
To generate expressions from a character vector, use parse(text=...):
lbls <- c("E^A","S^P","lambda","T","E^Q","E^Q","AT")
x <- 1:length(lbls)
y <- runif(length(lbls))
# I'm just going to draw labels on the (x,y) points.
plot(x,y,'n')
text(x,y, labels=parse(text=lbls)) # see the parse(text=lbls) ?

Resources