Numpy 2d and 1d array to latex bmatrix

Question:

I’m looking for a clean way to migrate numpy arrays to latex bmatrix. It should work for both 2d arrays and horizontal and vertical 1d array.

Example

A = array([[12, 5, 2],
           [20, 4, 8],
           [ 2, 4, 3],
           [ 7, 1,10]])

print A              #2d array
print A[0]           #horizontal array
print A[:,0, None]   #vertical array

array_to_bmatrix(A)
array_to_bmatrix(A[0])
array_to_bmatrix(A[:,0, None])

Out:

[[12  5  2]
 [20  4  8]
 [ 2  4  3]
 [ 7  1 10]]

[12  5  2]

[[12]
 [20]
 [ 2]
 [ 7]]

begin{bmatrix} 
 12.000 & 5.000 & 2.000 & \
 20.000 & 4.000 & 8.000 & \
 2.000 & 4.000 & 3.000 & \
 7.000 & 1.000 & 10.000 & \
end{bmatrix}

begin{bmatrix} 
 12.000 & 5.000 & 2.000
end{bmatrix}

begin{bmatrix} 
 12.000 & \
 20.000 & \
 2.000 & \
 7.000 & \
end{bmatrix}

Attempt of solution

def array_to_bmatrix(array):
    begin = '\begin{bmatrix} n'
    data = ''
    for line in array:        
        if line.size == 1:
            data = data + ' %.3f &'%line
            data = data + r' \'
            data = data + 'n'
            continue
        for element in line:
            data = data + ' %.3f &'%element

        data = data + r' \'
        data = data + 'n'
    end = 'end{bmatrix}'
    print begin + data + end  

This solution works for vertical and 2d arrays, however it outputs horizontal arrays as vertical ones.

array_to_bmatrix(A[0])

Out:

begin{bmatrix} 
 12.000 & \
 5.000 & \
 2.000 & \
end{bmatrix}

Answers:

When you do this:

    for line in array:

you are iterating over the first dimension of array. When the array is 1-D, you end up iterating over the values. You need to ensure that array is really 2-D before doing this iteration. One way is to pass the argument through numpy.atleast_2d:

import numpy as np

def array_to_bmatrix(array):
    array = np.atleast_2d(array)
    begin = '\begin{bmatrix} n'
    data = ''
    for line in array:

etc.

Answered By: Warren Weckesser

The __str__ method of the numpy array already does most of the formatting for you. Let’s exploit that;

import numpy as np

def bmatrix(a):
    """Returns a LaTeX bmatrix

    :a: numpy array
    :returns: LaTeX bmatrix as a string
    """
    if len(a.shape) > 2:
        raise ValueError('bmatrix can at most display two dimensions')
    lines = str(a).replace('[', '').replace(']', '').splitlines()
    rv = [r'begin{bmatrix}']
    rv += ['  ' + ' & '.join(l.split()) + r'\' for l in lines]
    rv +=  [r'end{bmatrix}']
    return 'n'.join(rv)

A = np.array([[12, 5, 2], [20, 4, 8], [ 2, 4, 3], [ 7, 1, 10]])
print bmatrix(A) + 'n'

B = np.array([[1.2], [3.7], [0.2]])
print bmatrix(B) + 'n'

C = np.array([1.2, 9.3, 0.6, -2.1])
print bmatrix(C) + 'n'

This returns:

begin{bmatrix}
  12 & 5 & 2\
  20 & 4 & 8\
  2 & 4 & 3\
  7 & 1 & 10\
end{bmatrix}

begin{bmatrix}
  1.2\
  3.7\
  0.2\
end{bmatrix}

begin{bmatrix}
  1.2 & 9.3 & 0.6 & -2.1\
end{bmatrix}
Answered By: Roland Smith

I am not satisfied with using the printed output from Python. The matrix may be too big, which causes wrapping.
This is code for to print the LaTeX text for a 2d matrix.

def bmatrix(a):
    text = r'$left[begin{array}{*{'
    text += str(len(a[0]))
    text += r'}c}'
    text += 'n'
    for x in range(len(a)):
        for y in range(len(a[x])):
            text += str(a[x][y])
            text += r' & '
        text = text[:-2]
        text += r'\'
        text += 'n'
    text += r'end{array}right]$'

    print text

Which gives this

$left[begin{array}{*{16}c}
2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 \
0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 \
0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 \
-1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \
0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \
0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \
0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 \
0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 \
0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 & 0 \
0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 & 0 \
0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 & 0 \
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 & 0 \
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 & -1 \
-1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 & 0 \
0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 & 0 \
0 & 0 & -1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 & 2.01 \
end{array}right]$
Answered By: HK Tong

Try array_to_latex (pip install). I wrote it for this very reason. Please provide your feedback where it falls short.

It has defaults, but also lets you customize formats (exponential, number of decimal places) and handles complex numbers as well and can “pop” the results right into your clipboard (no need to copy text dumped to the screen).

Some examples in the github repository. https://github.com/josephcslater/array_to_latex

Answered By: Joseph C. Slater

I’ve made the attempt to make a comprehensive solution so that individuals don’t need to write up even a minimal script to get it done. I’ve put in flexibility for floats, formatting, complex, and Pandas arrays. Please use, and provide feedback to, (array_to_latex)[https://pypi.org/project/array-to-latex/] .

Answered By: Joseph C. Slater

In addition, to the answers before, you can generate the latex from the array this way

from IPython.display import *
from numpy import *
A = array([[12, 5, 2],
       [20, 4, 8],
       [ 2, 4, 3],
       [ 7, 1,10]])

latexA = '$$n' + r'begin{bmatrix}' + 'n' + (r'\' + 'n').join('&'.join(str(x) for x in row) for row in A) + 'n' + r'end{bmatrix}' + 'n' +'$$'
print(latexA)

display(Latex(latexA))

print output is as follows.

$$
begin{bmatrix}
12&5&2\
20&4&8\
2&4&3\
7&1&10
end{bmatrix}
$$
Answered By: I_Al-thamary

Another option is to use sympy: first convert the array to a sympy.Matrix and then use the sympy.latex function.

Answered By: macleginn

A further answer, inspired by Roland Smith’s answer:

def matToTex(a, roundn=2, matrixType = "b",rowVector = False):
    if type(a) != np.ndarray:
        raise ValueError("Input must be np array")
    if len(a.shape) > 2:
        raise ValueError("matrix can at most display two dimensions")
    if matrixType not in ["b","p"]:
        raise ValueError("matrix can be either type "b" or type "p"")
    if rowVector:
        if not (len(a.shape) != 1 or a.shape[0] != 1):
            raise ValueError("Cannot rowVector this bad boi, it is not a vector!")
    lines = str(a).splitlines()
    ret = "n\begin{"+matrixType+"matrix}n"
    for line in lines:
        line = re.sub("s+",",",re.sub("[|]","",line).strip())
        nums = line.split(",");
        if roundn != -1:
            nums = [str(round(float(num),roundn)) for num in nums]
        if rowVector:
            ret += " \\n".join(nums)
        else:
            ret += " & ".join(nums)+" \\ n"
    ret += "n\end{"+matrixType+"matrix}n"
    ret = re.sub("(-){0,1}0.[0]* ","0 ",ret)
    print(ret)
Answered By: GregarityNow

yet another, inspired by Roland Smith’s answer
support scientific notation format

def bmatrix(a):
    """Returns a LaTeX bmatrix

    :a: numpy array
    :returns: LaTeX bmatrix as a string
    """
    if len(a.shape) > 2:
        raise ValueError('bmatrix can at most display two dimensions')
    temp_string = np.array2string(a, formatter={'float_kind':lambda x: "{:.2e}".format(x)})
    lines = temp_string.replace('[', '').replace(']', '').splitlines()
    rv = [r'begin{bmatrix}']
    rv += ['  ' + ' & '.join(l.split()) + r'\' for l in lines]
    rv +=  [r'end{bmatrix}']
    return 'n'.join(rv)

result:

begin{bmatrix}
  7.53e-04 & -2.93e-04 & 2.04e-04 & 5.30e-05 & 1.84e-01 & -2.43e-05\
  -2.93e-04 & 1.19e-01 & 2.96e-01 & 2.19e-01 & 1.98e+01 & 8.61e-03\
  2.04e-04 & 2.96e-01 & 9.60e-01 & 7.42e-01 & 4.03e+01 & 2.45e-02\
  5.30e-05 & 2.19e-01 & 7.42e-01 & 6.49e-01 & 2.82e+01 & 1.71e-02\
  1.84e-01 & 1.98e+01 & 4.03e+01 & 2.82e+01 & 5.75e+03 & 1.61e+00\
  -2.43e-05 & 8.61e-03 & 2.45e-02 & 1.71e-02 & 1.61e+00 & 7.04e-03\
end{bmatrix}
Answered By: apoptosis

If you happen to use qiskit by any chance, you may try a sleek method array_to_latex from qiskit.visualization.

See here:

Sample snippet:

from qiskit.visualization import array_to_latex
import numpy as np

x = np.zeros(100).reshape(10,10)


# Max rows and cols = 24
array_to_latex(array=x, prefix='Output = ', max_size=(10,10)) # If max_size not set then matrix will have ellipses
# print latex source only: Source=True
latex_source = array_to_latex(array=x, source=True, max_size=(10,10))

# If you are using Jupyter Notebook: 
from IPython.display import display, Markdown
display(Markdown(latex_source))

Sample output:

enter image description here

Answered By: Rajesh Swarnkar

Just to elaborate on macleginn answer.

import numpy as np
import sympy as sym
from IPython.display import display, Math
A = np.array([[12, 5, 2],
       [20, 4, 8],
       [ 2, 4, 3],
       [ 7, 1,10]])
A = sym.Matrix(A)
display(A)
Answered By: Jorge Zazueta
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.