49

As writing matrices in LaTeX is an extremely time-consuming activity, I was wondering if a software or a site exists that automatically gave the transposed form of a matrix, that is to say, given a matrix:

\begin{bmatrix}
   0 & -1 & -1 \\
   -1 & -1 & 0 \\
   -1 & 0 & 1 \\
   1 & 0 & 0 \\
   0 & 0 & -1 \\
   -1 & 2 & 1 
\end{bmatrix}

it will produce a transposed matrix, with the columns in place of the lines and conversely...

It would be particularly time-saving!

48

Here's an implementation in expl3:

\documentclass{article}
\usepackage{xparse}
\usepackage{amsmath}
\usepackage{environ}

\ExplSyntaxOn
\NewEnviron{bmatrixT}
 {
  \marine_transpose:V \BODY
 }

\int_new:N \l_marine_transpose_row_int
\int_new:N \l_marine_transpose_col_int
\seq_new:N \l_marine_transpose_rows_seq
\seq_new:N \l_marine_transpose_arow_seq
\prop_new:N \l_marine_transpose_matrix_prop
\tl_new:N \l_marine_transpose_last_tl
\tl_new:N \l_marine_transpose_body_tl

\cs_new_protected:Nn \marine_transpose:n
 {
  \seq_set_split:Nnn \l_marine_transpose_rows_seq { \\ } { #1 }
  \int_zero:N \l_marine_transpose_row_int
  \prop_clear:N \l_marine_transpose_matrix_prop
  \seq_map_inline:Nn \l_marine_transpose_rows_seq
   {
    \int_incr:N \l_marine_transpose_row_int
    \int_zero:N \l_marine_transpose_col_int
    \seq_set_split:Nnn \l_marine_transpose_arow_seq { & } { ##1 }
    \seq_map_inline:Nn \l_marine_transpose_arow_seq
     {
      \int_incr:N \l_marine_transpose_col_int
      \prop_put:Nxn \l_marine_transpose_matrix_prop
       {
        \int_to_arabic:n { \l_marine_transpose_row_int }
        ,
        \int_to_arabic:n { \l_marine_transpose_col_int }
       }
       { ####1 }
     }
   }
   \tl_clear:N \l_marine_transpose_body_tl
   \int_step_inline:nnnn { 1 } { 1 } { \l_marine_transpose_col_int }
    {
     \int_step_inline:nnnn { 1 } { 1 } { \l_marine_transpose_row_int }
      {
       \tl_put_right:Nx \l_marine_transpose_body_tl
        {
         \prop_item:Nn \l_marine_transpose_matrix_prop { ####1,##1 }
         \int_compare:nF { ####1 = \l_marine_transpose_row_int } { & }
        }
      }
     \tl_put_right:Nn \l_marine_transpose_body_tl { \\ }
    }
   \begin{bmatrix}
   \l_marine_transpose_body_tl
   \end{bmatrix}
 }
\cs_generate_variant:Nn \marine_transpose:n { V }
\cs_generate_variant:Nn \prop_put:Nnn { Nx }
\ExplSyntaxOff

\begin{document}
\[
\begin{bmatrix}
   0 & -1 & -1 \\
   -1 & -1 & 0 \\
   -1 & 0 & 1 \\
   1 & 0 & 0 \\
   0 & 0 & -1 \\
   -1 & 2 & 1 
\end{bmatrix}^T
=
\begin{bmatrixT}
   0 & -1 & -1 \\
   -1 & -1 & 0 \\
   -1 & 0 & 1 \\
   1 & 0 & 0 \\
   0 & 0 & -1 \\
   -1 & 2 & 1 
\end{bmatrixT}
\]

\end{document}

enter image description here

  • 8
    you are a few years late.... darn, this would have saved some grey hair. – percusse Dec 14 '15 at 22:32
  • 1
    @percusse Well, the code is pretty straightforward, isn't it? – egreg Dec 14 '15 at 22:35
  • 15
    In riemannian geometry yes they might be straight. – percusse Dec 14 '15 at 22:43
  • 1
    @percusse: I am too stoopid to understand this witty comment. :) – Paulo Cereda Dec 15 '15 at 7:12
  • @PauloCereda Replace line, angle, parallel with bla, BLA, Bla and you are done. – percusse Dec 15 '15 at 20:17
23

update: better commented code, safer inner macro names with a \Mar@ prefix, added tabular, "macro" and "file" example.

Here is an approach based on an expandable macro \Transpose. One can use it inside pmatrix, bmatrix, ..., or tabular-like environments.

The macro is used as \Transpose {rows separated by \\} where each row is written with & separators and the final row is supposed to have no \\.

The \Transpose expands in two steps. Brace removal is possible for some items, I have not gone into extreme details, anyhow tabular cells have local scope.

But I suspect you would be better off with text editor macros ; surely possible to do for example in an Emacs buffer, for someone knowledgeable enough in e-Lisp. Indeed, I guess the typical use case is with big tabular material one needs to edit further after transpose, to re-insert into the TeX source.

As an alternative to learning e-Lisp, one could use \Transpose to write its output to some auxiliary file in a draft run, so the user could recover the transposed data. This is also illustrated in the code sample next.

\documentclass{article}

\usepackage{amsmath}
\usepackage{array}

\makeatletter
\catcode`! 3
\catcode0 12

% The update chooses safer macro names.

% It could be useful to allow #1 to be itself a macro expanding
% to some rows. One could replace \Mar@DoOneRow by 
% \expandafter\Mar@DoOneRow but then general usage must be aware
% of this one-expansion of contents.

% Usage: \Transpose { &-separated cells \\ &-separated cells \\ ...
%                     ...\\&-separated cells and *no* final \\ }

% Can be used inside amsmath matrices as well as inside LaTeX tabular's
% 
\def\Transpose #1{\romannumeral0\expandafter
                  \Mar@Transpose@a\romannumeral`^^@\Mar@DoOneRow #1\\!\\}

\def\Mar@DoOneRow #1\\{\Mar@DoOneRow@a {}#1&^^@&}%

\def\Mar@DoOneRow@a #1#2&{%
    \if^^@\detokenize{#2}\expandafter\@gobble\fi
    \Mar@DoOneRow@a {#1#2\\}%
}%

% unbraced #1 here will end in \\^^@\\
\def\Mar@Transpose@a #1#2\\{\ifx!#2\expandafter\Mar@FinishTranspose\fi
    \expandafter\Mar@Transpose@b\romannumeral`^^@\Mar@DoOneRow@a {}#2&^^@&#1}

% unbraced #1 here will end with \\^^@\\
% It represents a new transposed row with an extra ^^@ cell.
% The #2 here ends in \\. It holds the first already transposed rows.
\def\Mar@Transpose@b #1#2^^@\\{\Mar@Join {}#2^^@!#1}

% when #3=^^@ happens after #4\\ there is still ^^@\\
% update slightly simplifies \Mar@Join.
\def\Mar@Join #1#2\\#3!#4\\%
   {\if^^@\detokenize{#3}\expandafter\Mar@EndJoin\fi
    \Mar@Join {#1#2&#4\\}#3!}%

% unbraced #1 ends with \\
\def\Mar@EndJoin\Mar@Join #1^^@!^^@\\{\Mar@Transpose@a {#1^^@\\}}

\def\Mar@FinishTranspose
    #1&^^@&#2\\^^@\\{ #2}% the \\^^@\\ pattern helps removing a final \\

\catcode`! 12
\catcode0 15 % null character "invalid": this is default LaTeX setting.
\makeatother

\begin{document}

A bmatrix example:
\[
\begin{bmatrix}
    0 & -1 & -1 \\
   -1 & -1 & 0  \\
   -1 & 0  & 1  \\
    1 & 0  & 0  \\
    0 & 0  & -1 \\
   -1 & 2  & 1
\end{bmatrix}\longrightarrow
\begin{bmatrix}
  \Transpose {
    0 & -1 & -1 \\
   -1 & -1 & 0  \\
   -1 & 0  & 1  \\
    1 & 0  & 0  \\
    0 & 0  & -1 \\
   -1 & 2  & 1 }
\end{bmatrix}
\]

% works the same.
% \[
% \begin{pmatrix}
%   \Transpose {
%     0 & -1 & -1 \\
%    -1 & -1 & 0  \\
%    -1 & 0  & 1  \\
%     1 & 0  & 0  \\
%     0 & 0  & -1 \\
%    -1 & 2  & 1 }
% \end{pmatrix}
% \]

A tabular example:

\begin{center}
\begin{tabular}{c|>{\bfseries}c|>{\itshape}c}
  L1 & L2 & L3 \\
  M1 & M2 & M3 \\
  N1 & N2 & N3
\end{tabular}
${}\longrightarrow{}$
\begin{tabular}{c|>{\bfseries}c|>{\itshape}c}
  \Transpose{
  L1 & L2 & L3 \\
  M1 & M2 & M3 \\
  N1 & N2 & N3
}% <- this to avoid a spurious space which tabular does not remove
\end{tabular}
\end{center}

A macro-level example to illustrate that two expansion steps are enough and
that contents are not prematurely expanded:

% spaces from endlines and around tabs
% which disappear in tabular/matrix treatments
% are not trimmed by \Transpose itself 

\def\www {  
  \Arbitrary L1 & \Stuff L2 & \Here L3 \\
  M1 & M2 & M3 \\
  N1 & N2 & N3
}

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\zzz
\expandafter\expandafter\expandafter{\Transpose {
  \Arbitrary L1 & \Stuff L2 & \Here L3 \\
  M1 & M2 & M3 \\
  N1 & N2 & N3
}}

\ttfamily

\meaning\www

becomes

\meaning\zzz

% And finally a "write to file" example
\newwrite\testout

\immediate\openout\testout=\jobname-tranpose.out

\immediate\write\testout{\unexpanded\expandafter\expandafter\expandafter
   {\Transpose  {
  \Arbitrary L1 & \Stuff L2 & \Here L3 \\
  M1 & M2 & M3 \\
  N1 & N2 & N3
}}}

\end{document}

transposing tabulars and matrices

The "filename-transpose.out" file contains:

 \Arbitrary L1 & M1 & N1 \\ \Stuff L2 & M2 & N2 \\ \Here L3 & M3 & N3 
  • the \if^^@\detokenize{#3} type tests assume that the cells do not start with a null character ; as anyhow LaTeX declares them by default as invalid characters, this does not appear as a real restriction (and my code here reestablishes the "invalid" catcode for the null character ^^@ after the macro definitions). And for use with Plain TeX, there the catcode is set by default to "ignore", thus one would do \catcode0 9 at the end (as Plain does not use \\ like LaTeX, but \cr, a Plain TeX variant would need some other changes; and probably would not assume no final row delimiter). – user4686 Dec 15 '15 at 11:30
  • Note to myself: I should have arranged things so that \Mar@Join sees in the upcoming token stream first the new row and then the already transposed ones. Then the #3 would be shorter and the \detokenize would have to handle less things. Also, here I use extra-safe \if test with \detokenize but in \Mar@Transpose@ I use and \ifx test which is slightly less safe in case of unbalanced \if, \else, \fi tokens in #2. Such unbalanced things would probably break the matrix or tabular anyhow. Hence I could use \ifx tests everywhere. – user4686 Dec 16 '15 at 9:47
22

If you mix math and LaTeX then you should get familiar with the sagetex package. The CTAN link is here. This gives you the power of a computer algebra system while working with LaTeX.

\documentclass{article}
\usepackage{amsmath,amsfonts,amssymb}
\usepackage{sagetex}
\begin{document}
\begin{sagesilent}
latex.matrix_delimiters(left='[', right=']')
A = Matrix([[0,-1,-1],[-1,-1,0],[-1,0,1],[1,0,0],[0,0,-1],[-1,2,1]])
\end{sagesilent}
If $A = \sage{A}$ and $A^{\intercal} = \sage{A.transpose()}$ then 
$A \cdot A^{\intercal} = \sage{A*A.transpose()}$ and 
$A^{\intercal}\cdot A = \sage{A.transpose()*A}$
\end{document}

The math gets defined and calculations are typically made in sagesilent mode. When you need the calculation use \sage{} to get it.

The output of the code is shown below: enter image description here

As you can see, on the basis of your input of matrix A, Sage takes care of determining the transpose and the matrix multiplications thereby minimizing mistakes. LaTex and Sage is documented here. Some Sage documentation on matrices can be found here and here.

The only drawback is you need access to Sage. You can download it and install on your computer, but getting it to work isn't always simple. But if you don't mind working in the cloud then you can get a free Sagemath Cloud account here. That's really simple and you can be up and running in a couple of minutes.

5

The easiest way to transpose a matrix x is use t(x) in a R chunk of a Sweave/knitr file (.Rnw). Then only left print as a bmatrix LaTeX environment using xtable or with a simple R function. A MWE with the second approach compiled with knitr:

mwe

\documentclass{article}
\usepackage{amsmath}
\parindent0pt
<<bmatrix,echo=F>>=
options(digits=2) 
x <- matrix(rnorm(18), 6 ,3) 
bmatrix <- function(matr) {
printmrow <- function(x) {cat(cat(x,sep=" & "),"\\\\ \n")}
cat("\\begin{bmatrix}","\n")
body <- apply(matr,1,printmrow)
cat("\\end{bmatrix}")}
@
\begin{document}

Source matrix in R: 
<<smatrix,echo=F,comment=NA>>=
x
@
The same matrix in math mode in \LaTeX :
\[
<<mmatrix,echo=F,results='asis'>>=
bmatrix(round(x,1))
@
^T =
<<tmatrix,echo=FALSE,results='asis'>>=
bmatrix(t(round(x,1)))
@
\]
\end{document}
2

Here's a simple implementation using stacks. Note that the standard stacking parameters like \setstacktabbedgap (inter-column gap), \stackalignment (column alignment), \setstackgap{L}{} (inter-row baselineskip), and even the tabbing character (\setstackTAB{&} is the implied default) carries over to the newly defined \bracketMatrixstackT macro.

\documentclass{article}
\usepackage{tabstackengine}
\setstacktabbedgap{2ex}% WORKS ON BOTH MATRIX & TRANSPOSE
\def\stackalignment{r}% WORKS ON BOTH MATRIX & TRANSPOSE
\setstackgap{L}{1.2\baselineskip}% WORKS ON BOTH MATRIX & TRANSPOSE
\makeatletter
\def\bracketMatrixstackT#1{%
  \expandafter\setstackEOL\expandafter{\TAB@char}%
  \left[\bms#1\\\relax\relax\right]%
}
\def\bms#1\\#2\relax{%
  \Centerstack{#1}\if\relax#2\relax\else%
  \hspace{\tabbed@gap}\bms#2\relax\fi%
}
\makeatother
\begin{document}
\[
\bracketMatrixstack{
1 & 2 & 3 & 4\\
5 & 6 & 7 & 8\\
9 & 10 & 11& 12
}
=
\bracketMatrixstackT{
1 & 2 & 3 & 4\\
5 & 6 & 7 & 8\\
9 & 10 & 11& 12
}^\mathrm{T}
\]
\end{document}

enter image description here

2

Not really a TeX answer, but might still be useful for someone. With Emacs you can switch from LaTeX/AUCTeX to Calc mode, do matrix operations and get back.

Let's say we have a bmatrix we want to transpose

\[
\begin{bmatrix}
    0  & -1 & -1 \\
    -1 & -1 &  0 \\
    -1 &  0 &  1 \\
     1 &  0 &  0 \\
     0 &  0 & -1 \\
    -1 &  2 &  1 
\end{bmatrix}
\]

Place the cursor inside the environment and press C-x * e to enter Calc embedded mode

\[
\begin{pmatrix} 0 & -1 & 
 -1 \\ -1 & -1 & 0 \\ -1 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 0 & -1 \\ -1 & 2 & 1 \end{pmatrix}
\]

Calc understood LaTeX syntax but messed up the alignment and turned bmatrix into a pmatrix. We'll get back to this later on.

Press d N to switch to normal Calc display mode, which you may find a little nicer to work on

% [calc-mode: language: nil]
\[
[ [ 0,  -1, -1 ]
  [ -1, -1, 0  ]
  [ -1, 0,  1  ]
  [ 1,  0,  0  ]
  [ 0,  0,  -1 ]
  [ -1, 2,  1  ] ]
\]

v t to transpose

% [calc-mode: language: nil]
\[
[ [ 0,  -1, -1, 1, 0,  -1 ]
  [ -1, -1, 0,  0, 0,  2  ]
  [ -1, 0,  1,  0, -1, 1  ] ]
\]

C-2 d L gets us back to LaTeX syntax, C-2 is an optional prefix that formats it as a 2D matrix with the correct alignment

% [calc-mode: language: (latex 2)]
\[
\begin{pmatrix}
0 & -1 & -1 & 1 & 0 & -1 \\ 
-1 & -1 & 0 & 0 & 0 & 2 \\ 
-1 & 0 & 1 & 0 & -1 & 1
\end{pmatrix}
\]

C-x * e disables Calc embedded mode and gets us back to normal editing. Now the only issue is that we have a pmatrix instead of the original bmatrix. This unfortunately is expected and documented in Calc docs... but it's trivial to fix! If you're using AucTeX just press C-u C-c C-e inside the matrix and enter bmatrix.

  • good to learn Calc knows LaTeX ! It seems it will lose bmatrix which becomes pmatrix. Perhaps you could enhance your answer with step by step explanation and what one sees. Also the conversion to Calc matrix notation with brackets and commas is nice. – user4686 Dec 18 '15 at 12:50
  • Updated the answer, pmatrix thing unfortunatly expected: you may need to edit this afterwards to change to your preferred matrix form ...from Calc docs – filippo Dec 19 '15 at 14:50
  • very nice ! +1.. in fact for me this is the best approach (but not everyone is emacs's user...). – user4686 Dec 19 '15 at 16:17
1

An easy solution to this kind of problem is to generate your LaTeX from Python.

I have written a small library for myself that generates TikZ code after I gave up fighting limitations of LaTeX.

Given an array, say

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])

Then, you can generate a LaTeX array:

def print_two_dimensional(a):
    print(r"\begin{bmatrix}")
    for r in range(a.shape[0]):
        print(" & ".join(str(x) for x in a[r]), r"\\")
    print(r"\end{bmatrix}")

Putting the first two snippets together, you call the function:

print_two_dimensional(a)

To print the transpose:

print_two_dimensional(a.T)

Putting it all together produces:

\begin{bmatrix}
1 & 2 & 3 \\
4 & 5 & 6 \\
\end{bmatrix}
\begin{bmatrix}
1 & 4 \\
2 & 5 \\
3 & 6 \\
\end{bmatrix}

The advantage of this solution is that you can also programmatically generate your matrices.

Here's a more involved example:

import numpy as np
from contextlib import contextmanager

@contextmanager
def tex_environment(name):
    print(r"\begin{", name, "}", sep="")
    yield
    print(r"\end{", name, "}", sep="")

def texify_array(a):
    """
    Texifies a numpy array of up to two dimensions.
    """
    if len(a.shape) == 0:
        print(a)
        return
    with tex_environment("bmatrix"):
        if len(a.shape) == 2:
            for r in range(a.shape[0]):
                print(" & ".join(str(x) for x in a[r]), r"\\")
        elif len(a.shape) == 1:
            for r in range(a.shape[0]):
                print(a[r], r"\\")


# Example begins here! ---------------------------------------------------------

a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([8, 1, 4])

with tex_environment("align"):
    texify_array(a)
    texify_array(b)
    print(" &= ")
    texify_array(a @ b)

produces:

\begin{align}
\begin{bmatrix}
1 & 2 & 3 \\
4 & 5 & 6 \\
\end{bmatrix}
\begin{bmatrix}
8 \\
1 \\
4 \\
\end{bmatrix}
 &=
\begin{bmatrix}
22 \\
61 \\
\end{bmatrix}
\end{align}
  • You should probably wrote a full Python script to show how your code work. Some people that may use LaTeX and matrix are not familiar with Python – Romain Picot Jan 7 '16 at 8:07
  • 1
    @RomainPicot It's now a full script if you put all the snippets together. – Neil G Jan 7 '16 at 8:09
1

Here is a MATLAB function to convert matrices to LaTeX strings:

function tex_str = tex_matrix(A,n_format)
if nargin<2
    n_format = '%d'; % Default number representation
end
[I,J] = size(A);

tex_str = sprintf('\\begin{bmatrix}\n');
for ii = 1:I
  tex_str = [tex_str,sprintf(['  ',n_format],A(ii,1))];
  for jj=2:J
    tex_str = [tex_str,sprintf([' & ',n_format], A(ii,jj))];
  end;
  if ii<I
    tex_str = [tex_str,sprintf(' \\\\\n')];
  else
    tex_str = [tex_str,sprintf('\n')];
  end
end
tex_str = [tex_str,'\end{bmatrix}'];

The second (optional) argument can be used to specify the format of the matrix's entries, with the syntax of fprintf.

Example usage:

>> A = [1,2,3,4;...
        5,6,7,8;...
        9,10,11,12];
>> tex_matrix(A)

ans =

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

>> tex_matrix(A.')

ans =

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

>> tex_matrix(0.1*A,'%.1f')

ans =

\begin{bmatrix}
  0.1 & 0.2 & 0.3 & 0.4 \\
  0.5 & 0.6 & 0.7 & 0.8 \\
  0.9 & 1.0 & 1.1 & 1.2
\end{bmatrix}
1

Another pure LaTeX solution is to save the matrix in some unique name, then to reuse this matrix while rotating it at the same time.

Note that (see why here) you can not use a simple ampersand as a separator when using a command to typeset matrices with tikz.

Note also that the last \\ is mandatory (otherwise you will get a missing } error).

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{matrix}

\newcommand{\mycustommatrix}[2]{
  \global\expandafter\def\csname mycustommatrixnamed#1\endcsname{#2}
  \left [ \begin{tikzpicture}[baseline=-0.5ex]
    \matrix[matrix of math nodes, ampersand replacement=\&] { \csname mycustommatrixnamed#1\endcsname };
  \end{tikzpicture} \right ]
}

\newcommand{\mycustomtranspose}[1]{
  \left [ \rotatebox[origin=c]{90}{\reflectbox{ \begin{tikzpicture}[baseline=-0.5ex]
    \matrix[matrix of math nodes, ampersand replacement=\&, nodes={rotate=90,xscale=-1}] { \csname mycustommatrixnamed#1\endcsname };
  \end{tikzpicture} }} \right ]
}

\begin{document}

$A = \mycustommatrix{A}{
  1 \& 0 \& -1 \\
  2 \& 3 \& 1 \\
}$

$A^T = \mycustomtranspose{A}$

\end{document}

Result

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.