# Infix mathematical notation in Incanter

I obviously love Clojure’s prefix notation, but there are times when it is more concise, and familiar, to represent mathematical formulae using infix notation, so I have integrated the infix portion of Jeffrey Bester’s Clojure math library into Incanter. There is now a formula macro called `\$=` for evaluating infix mathematical formulas in incanter.core.

Here’s an example,

```user> (use 'incanter.core)
nil
user> (\$= 7 + 8 - 2 * 6 / 2)
9
```

Note that there must be spaces between values and operators.

Vectors can be used instead of scalars. For instance, to add 5 to each element of the vector [1 2 3],

```user> (\$= [1 2 3] + 5)
(6 7 8)
```

or perform element-by-element arithmetic on vectors and matrices.

```user> (\$= [1 2 3] + [4 5 6])
(5 7 9)

user> (\$= [1 2 3] * [1 2 3])
(1 4 9)

user> (\$= [1 2 3] / [1 2 3])
(1 1 1)

user> (\$= (matrix [[1 2] [4 5]]) + 6)
[ 7.0000  8.0000
10.0000 11.0000]

user> (\$= (trans [[1 2] [4 5]]) + 6)
[7.0000 10.0000
8.0000 11.0000]
```

Examples of exponents using the ** function.

```user> (\$= 8 ** 3)
512.0

user> (\$= 8 ** 1/2)
2.8284271247461903

user> (\$= 2 ** -2)
0.25

user> (\$= [1 2 3] ** 2)
(1.0 4.0 9.0)
```

Parens can be used for grouping,

```user> (\$= 10 + 20 * (4 - 5) / 6)
20/3

user> (\$= (10 + 20) * 4 - 5 / 6)
715/6

user> (\$= 10 + 20 * (4 - 5 / 6))
220/3
```

including arbitrarily nested groupings.

```user> (\$= ((((5 + 4) * 5))))
45
```

Of course, variables can be used within the formula macro,

```user> (let [x 10
y -5]
(\$= x + y / -10))
21/2
```

and mathematical functions like sin, cos, tan, sq, sqrt, etc. can be used with standard Clojure prefix notation.

```user> (\$= (sqrt 5) * 5 + 3 * 3)
20.18033988749895

user> (\$= sq [1 2 3] + [1 2 3])
(2 6 12)

user> (\$= sin 2 * Math/PI * 2)
5.713284232087328

user> (\$= (cos 0) * 10)
10.0

user> (\$= (tan 2) * Math/PI * 10)
-68.64505182223235

user> (\$= (asin 1/2) * 10)
5.23598775598299

user> (\$= (acos 1/2) * 10)
10.47197551196598

user> (\$= (atan 1/2) * 10)
4.636476090008061
```

Functions can also be applied to vectors,

```user> (\$= [1 2 3] / (sq [1 2 3]) + [5 6 7])
(6 13/2 22/3)

user> (\$= [1 2 3] + (sin [4 5 6]))
(0.2431975046920718 1.0410757253368614 2.720584501801074)
```

Boolean tests are also supported.

```user> (\$= 3 > (5 * 2/7))
true

user> (\$= 3 <= (5 * 2/7))
false

user> (\$= 3 != (5 * 2/7))
true

user> (\$= 3 == (5 * 2/7))
false

user> (\$= 3 != 8 && 6 < 12)
true

user> (\$= 3 != 8 || 6 > 12)
true
```

Matrix multiplication uses the <*> function (equivalent to R’s %*% operator).

```user> (\$= [1 2 3] <*> (trans [1 2 3]))
[1.0000 2.0000 3.0000
2.0000 4.0000 6.0000
3.0000 6.0000 9.0000]

user> (\$= (trans [[1 2] [4 5]]) <*> (matrix [[1 2] [4 5]]))
[17.0000 22.0000
22.0000 29.0000]

user> (\$= (trans [1 2 3 4]) <*> [1 2 3 4])
30.0

user> (\$= [1 2 3 4] <*> (trans [1 2 3 4]))
[1.0000 2.0000  3.0000  4.0000
2.0000 4.0000  6.0000  8.0000
3.0000 6.0000  9.0000 12.0000
4.0000 8.0000 12.0000 16.0000]
```

The Kronecker product uses the <x> function (equivalent to R’s %x% operator).

```user> (\$= [1 2 3] <x> [1 2 3])
[1.0000
2.0000
3.0000
2.0000
4.0000
6.0000
3.0000
6.0000
9.0000]

user> (\$= (matrix [[1 2] [3 4] [5 6]]) <x> 4)
[ 4.0000  8.0000
12.0000 16.0000
20.0000 24.0000]

user> (\$= (matrix [[1 2] [3 4] [5 6]]) <x> (matrix [[1 2] [3 4]]))
[ 1.0000  2.0000  2.0000  4.0000
3.0000  4.0000  6.0000  8.0000
3.0000  6.0000  4.0000  8.0000
9.0000 12.0000 12.0000 16.0000
5.0000 10.0000  6.0000 12.0000
15.0000 20.0000 18.0000 24.0000]

user> (\$= [1 2 3 4] <x> 4)
[ 4.0000
8.0000
12.0000
16.0000]

user> (\$= [1 2 3 4] <x> (trans [1 2 3 4]))
[1.0000 2.0000  3.0000  4.0000
2.0000 4.0000  6.0000  8.0000
3.0000 6.0000  9.0000 12.0000
4.0000 8.0000 12.0000 16.0000]
```

Here’s an example using the formula macro in a function-plot of $x^3 - 5x^2 + 3x +5$, (I will use the incanter.latex/add-latex function to add a LaTeX annotation to the chart).

```(use '(incanter core charts latex))
(doto (function-plot (fn [x] (\$= x ** 3 - 5 * x ** 2 + 3 * x + 5)) -10 10)
(add-latex 0 250 "x^3 - 5x^2 + 3x +5")
view)
```

The next example will use the car-speed-to-breaking-distance sample data (the :cars dataset). I’ll partition the data, first selecting rows where the ratio of dist/speed is less than 2, then selecting rows where the ratio is greater than 2, and finally adding a line showing this threshold.

First, use the `with-data` macro, passing it the :cars sample data. Then apply the `\$where` function in order to filter the data; pass it a `\$fn`, which is a bit of syntax sugar around Clojure’s `fn` function that does map destructuring for functions that operate on dataset rows. For instance

(\$fn [x y] (…))

becomes

(fn [{:keys x y}] (…))

The parameter names specified in \$fn must correspond to the column names of the dataset.

```(use '(incanter core datasets charts))
(with-data (get-dataset :cars)
(doto (scatter-plot :speed :dist
:data (\$where (\$fn [speed dist]
(\$= dist / speed < 2))))
:data (\$where (\$fn [speed dist]
(\$= dist / speed >= 2))))
(add-lines (\$ :speed) (\$= 2 * (\$ :speed)))
view))
```

The complete code for this post is available here.

### 2 responses to “Infix mathematical notation in Incanter”

1. hohonuuli

Very nicely done. I like the infix-math.

2. Paul Hobbs

This is awesome! Very well done on the infix math and vectorized operators. Clojure is quickly becoming my favorite language!