49

You can get a coefficient of a specific term by using coeff();

x, a = symbols("x, a")
expr = 3 + x + x**2 + a*x*2
expr.coeff(x)
# 2*a + 1

Here I want to extract all the coefficients of x, x**2 (and so on), like;

# for example
expr.coefficients(x)
# want {1: 3, x: (2*a + 1), x**2: 1}

There is a method as_coefficients_dict(), but it seems this doesn't work in the way I want;

expr.as_coefficients_dict()
# {1: 3, x: 1, x**2: 1, a*x: 2}
expr.collect(x).as_coefficients_dict()
# {1: 3, x**2: 1, x*(2*a + 1): 1}
akai
  • 1,986
  • 3
  • 17
  • 37
  • 1
    Are there limits on your expression `expr`, i.e. is it always a polynomial? Is its degree limited? – Carsten Apr 09 '14 at 08:12
  • 1
    @Carsten It would be great if there's an "unlimited" way, and in fact I think there must be especially because collect() is (probably) unlimited, but at least a method that works on a polynomial is needed. – akai Apr 09 '14 at 20:28

4 Answers4

56

all_coeffs() can be sometime better than using coeffs() for a Poly. The difference lies in output of these both. coeffs() returns a list containing all coefficients which has a value and ignores those whose coefficient is 0 whereas all_coeffs() returns all coefficients including those whose coefficient is zero.

>>> a = Poly(x**3 + a*x**2 - b, x)
>>> a.coeffs()
[1, a, -b]

>>> a.all_coeffs()
[1, a, 0, -b]
Kundan
  • 571
  • 4
  • 4
  • 8
    Thanks. I was caught with my pants down by `coeffs()` ignoring zeroed coefficients. It's also worth noting that `numpy` uses the reverse ordering so when using `numpy` polynomial its worthwhile doing `a.reverse()` – Alexander McFarlane Jul 27 '16 at 17:09
42

The easiest way is to use Poly

>>> a = Poly(expr, x)
>>> a.coeffs()
[1, 2*a + 1, 3]
asmeurer
  • 75,821
  • 22
  • 150
  • 217
4

One thing you can do is use a dictionary comprehension like so:

dict = {x**p: expr.collect(x).coeff(x**p) for p in range(1,n)}

where n is the highest power+1. In this case n=3. So you would have the list [1,2]

This would give

dict = {x: (2*a+1), x**2: 1}

Then you can add in the single term with

dict[1] = 3

So

 dict = {1:3,x:(2*a+1),x**2:1}

You may also try:

a = list(reversed(expr.collect(x).as_ordered_terms()))
dict = {x**p: a[p],coeff(x**p) for p in range(1,n)}
dict[1] = a[0] # Would only apply if there is single term such as the 3 in the example

where n is the highest power + 1.

RDizzl3
  • 816
  • 6
  • 17
3

Collection of coefficients can be handled with Poly and then separation of the monomials into dependent and independent parts can be handled with Expr.as_independent:

>>> def codict(expr, *x):
...   collected = Poly(expr, *x).as_expr()
...   return dict(i.as_independent(*x)[::-1] for i in Add.make_args(collected))
...
>>> codict(y, x)
{1: 3, x**2: 1, x: 2*a + 1}
>>> codict(y+b*z,x,z)
{1: 3, x**2: 1, z: b, x: 2*a + 1}
smichr
  • 10,440
  • 2
  • 17
  • 24