A Hack to Create Matrices in R, Matlab style

[This article was first published on Publishable Stuff, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.


The Matlab syntax for creating matrices is pretty and convenient. Here is a 2×3 matrix in Matlab syntax where , marks a new column and ; marks a new row:

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">[<span style="color: #666666">1</span>, <span style="color: #666666">2</span>, <span style="color: #666666">3</span>;
 <span style="color: #666666">4</span>, <span style="color: #666666">5</span>, <span style="color: #666666">6</span>]
</pre></div>

Here is how to create the corresponding matrix in R:

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">matrix(c(<span style="color: #666666">1</span>,<span style="color: #666666">4</span>,<span style="color: #666666">2</span>,<span style="color: #666666">5</span>,<span style="color: #666666">3</span>,<span style="color: #666666">6</span>), <span style="color: #666666">2</span>, <span style="color: #666666">3</span>)
</pre></div>

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #408080; font-style: italic">##      [,1] [,2] [,3]</span>
<span style="color: #408080; font-style: italic">## [1,]    1    2    3</span>
<span style="color: #408080; font-style: italic">## [2,]    4    5    6</span>
</pre></div>

Functional but not as pretty, plus the default is to specify the values column wise. A better solution is to use rbind:

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">rbind(c(<span style="color: #666666">1</span>,<span style="color: #666666">2</span>,<span style="color: #666666">3</span>),
      c(<span style="color: #666666">4</span>,<span style="color: #666666">5</span>,<span style="color: #666666">6</span>))
</pre></div>

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #408080; font-style: italic">##      [,1] [,2] [,3]</span>
<span style="color: #408080; font-style: italic">## [1,]    1    2    3</span>
<span style="color: #408080; font-style: italic">## [2,]    4    5    6</span>
</pre></div>

Lately I’ve been reading up on the metaprogramming capabilities of R in Hadley Wickham’s great Advanced R programming (while it is freely available online, you can already pre-order the IRL version here). Using metaprogramming we can hack together a function that allow us to create matrices in a similar way as in Matlab. I’ll first show some examples of how the function works and after that I’ll show you the code. The function is called qm as in “quick matrix” where , is used to separate columns and | is used to separate rows:

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">qm(<span style="color: #666666">1</span>,<span style="color: #666666">2</span>,<span style="color: #666666">3|</span>
   <span style="color: #666666">4</span>,<span style="color: #666666">5</span>,<span style="color: #666666">6</span>)
</pre></div>

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #408080; font-style: italic">##      [,1] [,2] [,3]</span>
<span style="color: #408080; font-style: italic">## [1,]    1    2    3</span>
<span style="color: #408080; font-style: italic">## [2,]    4    5    6</span>
</pre></div>

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">qm(<span style="color: #666666">1:3</span> <span style="color: #666666">|</span> rnorm(<span style="color: #666666">3</span>) <span style="color: #666666">|</span> <span style="color: #666666">0</span>, <span style="color: #666666">0</span>, <span style="color: #666666">0</span>)
</pre></div>

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #408080; font-style: italic">##       [,1]   [,2]  [,3]</span>
<span style="color: #408080; font-style: italic">## [1,] 1.000 2.0000 3.000</span>
<span style="color: #408080; font-style: italic">## [2,] 2.421 0.9801 1.202</span>
<span style="color: #408080; font-style: italic">## [3,] 0.000 0.0000 0.000</span>
</pre></div>

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">qm(<span style="color: #666666">1|2|3|4</span>)
</pre></div>

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #408080; font-style: italic">##      [,1]</span>
<span style="color: #408080; font-style: italic">## [1,]    1</span>
<span style="color: #408080; font-style: italic">## [2,]    2</span>
<span style="color: #408080; font-style: italic">## [3,]    3</span>
<span style="color: #408080; font-style: italic">## [4,]    4</span>
</pre></div>

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #408080; font-style: italic"># qm is useful when defining covariance matrices, for example:</span>
library(MASS)
sigma <span style="color: #666666">=</span> qm( <span style="color: #666666">1</span> , <span style="color: #666666">0.7|</span>
           <span style="color: #666666">0.7</span>,  <span style="color: #666666">1</span> )
xy <span style="color: #666666"><-</span> mvrnorm(<span style="color: #666666">100</span>, c(<span style="color: #666666">0</span>, <span style="color: #666666">0</span>), sigma)
plot(xy, xlab <span style="color: #666666">=</span> <span style="color: #BA2121">"x"</span>, ylab <span style="color: #666666">=</span> <span style="color: #BA2121">"y"</span>)
</pre></div>

plot of chunk unnamed-chunk-7

Pretty cool, right? 🙂

Here is finally the full qm function. The trick is roughly to grab the arguments to qm as a list, split every argument with a | into two, and finally form the rows of the matrix by evaluating and concatenating the arguments between each |. (qm is not extensively tested so use it at your own risk and please tell me if you find any way to improve the code!)

<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">qm <span style="color: #666666"><-</span> <span style="color: #008000; font-weight: bold">function</span>(<span style="color: #008000; font-weight: bold">...</span>) {
    <span style="color: #408080; font-style: italic"># Get the arguments as a list</span>
    arg <span style="color: #666666"><-</span> eval(substitute(alist(<span style="color: #008000; font-weight: bold">...</span>)))
    <span style="color: #408080; font-style: italic"># Initialize l as a list of vecors, each vector in l corresponds to one row</span>
    <span style="color: #408080; font-style: italic"># of the matrix.</span>
    l <span style="color: #666666"><-</span> list(c())
    <span style="color: #408080; font-style: italic"># rhl_l is a list where we will push the rhs of expressions like 1 | 2 | 3 ,</span>
    <span style="color: #408080; font-style: italic"># which parses as (1 | 2) | 3 , while we deal with the left hand side (1 |</span>
    <span style="color: #408080; font-style: italic"># 2)</span>
    rhl_l <span style="color: #666666"><-</span> list()
    <span style="color: #008000; font-weight: bold">while</span> (length(arg) <span style="color: #666666">></span> <span style="color: #666666">0</span>) {
        a <span style="color: #666666"><-</span> arg[[<span style="color: #666666">1</span>]]
        arg <span style="color: #666666"><-</span> tail(arg, <span style="color: #666666">-1</span>)
        <span style="color: #008000; font-weight: bold">if</span> (a[[<span style="color: #666666">1</span>]] <span style="color: #666666">==</span> <span style="color: #BA2121">"|"</span>) {
            <span style="color: #408080; font-style: italic"># Push the left hand side of the ... | ... expression back on the arguments</span>
            <span style="color: #408080; font-style: italic"># list and push the rhs onto rhl_l</span>
            arg <span style="color: #666666"><-</span> c(a[[<span style="color: #666666">2</span>]], arg)
            rhl_l <span style="color: #666666"><-</span> c(a[[<span style="color: #666666">3</span>]], rhl_l)
        } <span style="color: #008000; font-weight: bold">else</span> {
            <span style="color: #408080; font-style: italic"># Just a normal element, that we'll evaluate and append to the last</span>
            <span style="color: #408080; font-style: italic"># vector/row in l.</span>
            l[[length(l)]] <span style="color: #666666"><-</span> c(l[[length(l)]], eval(a))
            <span style="color: #408080; font-style: italic"># If there are rhs elements left in rhs_l we'll append them as new</span>
            <span style="color: #408080; font-style: italic"># vectors/rows on l and then we empty rhs_l.</span>
            <span style="color: #008000; font-weight: bold">for</span> (i <span style="color: #008000; font-weight: bold">in</span> seq_along(rhl_l)) {
                l[[length(l) <span style="color: #666666">+</span> <span style="color: #666666">1</span>]] <span style="color: #666666"><-</span> eval(rhl_l[[i]])
            }
            rhl_l <span style="color: #666666"><-</span> list()
        }
    }
    do.call(rbind, l)
}
</pre></div>

While I’m not sure that qm is really a super useful function, I still think it is a nice example of what you can hack together using the metaprogramming facilities of R.

To leave a comment for the author, please follow the link and comment on their blog: Publishable Stuff.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)