将 SymPy 矩阵转换为 numpy 数组/矩阵的最佳方法是啥

Posted

技术标签:

【中文标题】将 SymPy 矩阵转换为 numpy 数组/矩阵的最佳方法是啥【英文标题】:What is the best way to convert a SymPy matrix to a numpy array/matrix将 SymPy 矩阵转换为 numpy 数组/矩阵的最佳方法是什么 【发布时间】:2013-06-08 19:45:14 【问题描述】:

我不确定我在sympy 中使用的将MutableDenseMatrix 转换为numpy.arraynumpy.matrix 的方法是否是当前的良好做法。

我有一个符号矩阵,如:

g = sympy.Matrix( [[   x,  2*x,  3*x,  4*x,  5*x,  6*x,  7*x,  8*x,   9*x,  10*x],
                   [x**2, x**3, x**4, x**5, x**6, x**7, x**8, x**9, x**10, x**11]] )

我正在转换为 numpy.array 做:

g_func = lambda val: numpy.array( g.subs( x:val ).tolist(), dtype=float )

我在哪里得到一个给定值 x 的数组。

SymPy 中是否有更好的内置解决方案来做到这一点?

谢谢!

【问题讨论】:

这个问题的大部分都在这里 ***.com/questions/10678843/… 得到回答 - 我知道这不是完全相同的问题,但它提供了关于 numpy/sympy 互操作性的所有必要信息。 谢谢!感觉要准备一个答案,因为我认为这也是我的案例的最佳方法...... 是的,使用lambdify(我现在懒得写答案)。 【参考方案1】:

此答案基于 Krastanov 和 asmeurer 的建议。这个小sn-p使用sympy.lambdify:

from sympy import lambdify
from sympy.abc import x, y

g = sympy.Matrix([[   x,  2*x,  3*x,  4*x,  5*x,  6*x,  7*x,  8*x,   9*x,  10*x],
                  [y**2, y**3, y**4, y**5, y**6, y**7, y**8, y**9, y**10, y**11]])
s = (x, y)
g_func = lambdify(s, g, modules='numpy')

其中g 是您的表达式,其中包含分组在s 中的所有符号。

如果使用modules='numpy',函数g_func的输出将是一个np.ndarray对象:

g_func(2, 3)
#array([[     2,      4,      6,      8,     10,     12,     14,     16,       18,     20],
#       [     9,     27,     81,    243,    729,   2187,   6561,  19683,    59049, 177147]])

g_func(2, y)
#array([[2, 4, 6, 8, 10, 12, 14, 16, 18, 20],
#       [y**2, y**3, y**4, y**5, y**6, y**7, y**8, y**9, y**10, y**11]], dtype=object)

如果modules='sympy' 输出是sympy.Matrix 对象。

g_func = lambdify(vars, g, modules='sympy')
g_func(2, 3)
#Matrix([[2,  4,  6,   8,  10,   12,   14,    16,    18,     20],
#        [9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147]])

g_func(2, y)
#Matrix([[   2,    4,    6,    8,   10,   12,   14,   16,    18,    20],
#        [y**2, y**3, y**4, y**5, y**6, y**7, y**8, y**9, y**10, y**11]])

【讨论】:

【参考方案2】:

从SymPy-0.7.6.1_mpmath_ matrix docs,存在tolist()方法:

最后,可以将矩阵转换为嵌套列表。这非常有用,因为大多数涉及矩阵或数组的 Python 库(即 NumPy 或 SymPy)都支持这种格式:

B.tolist()

【讨论】:

mpmath.matrices.matrices.tolist() 返回mpmath.ctx_mp_python.mpf 的列表,因此您仍然需要强制转换它,但是 IMO 这不是 OP 所要求的,因为他们想要一个生成 numpy 数组的函数,这就是接受的答案的作用。【参考方案3】:
 numpy.array(SympyMatrix.tolist()).astype(numpy.float64)

原生的tolist 方法将 sympy 矩阵变成嵌套索引的东西

numpy.array 可以将嵌套索引的内容转换为数组

.astype(float64) 会将数组的数字转换为默认的 numpy 浮点类型,这将与任意 numpy 矩阵操作函数一起使用。

作为附加说明 - 值得一提的是,通过强制转换为 numpy,您将失去执行矩阵运算的能力,同时保留 sympy 变量和表达式以备不时之需。

编辑: 我的补充说明的一点是,在转换为 numpy.array 时,您失去了在矩阵中的任何位置拥有变量的能力。你所有的矩阵元素必须在你施法之前已经是数字,否则一切都会破坏。

【讨论】:

我猜 .tolist() 不是必需的。 (由@turtles_are_cute 回答证明)【参考方案4】:

这看起来是最直接的:

np.array(g).astype(np.float64)

如果你跳过 astype 方法,numpy 将创建一个 'object' 类型的矩阵,它不适用于常见的数组操作。

【讨论】:

它有效。而 np.array(g, dtype=np.float64) 不会。

以上是关于将 SymPy 矩阵转换为 numpy 数组/矩阵的最佳方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

将 NumPy 向量转换为二维数组/矩阵

将numpy对象数组转换为稀疏矩阵

将数据框转换为 Numpy 数组 [重复]

如何将一系列数组转换为 pandas/numpy 中的单个矩阵?

将 2d 矩阵转换为 3d 单热矩阵 numpy

混合类型的 NumPy 数组/矩阵