ENH: plotting numerical expressions
State: closed

Passing the `y` argument of a plot to `DataFrame.eval` allows plotting a numerical expression.
Makes numerical data exploration much easier. E.g. graphically finding the norm of two curves.
See example here:
[example notebook](https://gist.github.com/TsvikiHirsh/46fd47bc35dc1874234d)

No support for multicolumn plotting, e.g. for `["a","4*b"]`
Should be very easy to apply the same on the `index`.

Could be very useful for data exploration, without modifying the original `DataFrame`


Labels:
name: Docs
name: Visualization
description: plotting

Comments:
My initial reaction is "too much magic"... but I could be biased. When `eval`/`query` was introduced there was concern that this was opening up a can of worms (a pandas DSL, distinct from python) Thoughts from others?

Also I _think_ that if you have a DataFrame like

``` python
df = pd.DataFrame({"a": [1, 2], "b": [3, 4], "a + b": [0, 1]})
```

Then under your change `df.plot('a + b')` will evaluate `df.a + df.b` shadowing the column named 'a + b', which would probably make this a non-starter. I do see how this could be convenient for exploration though.

@TomAugspurger Good points.
I still have to dig into `eval` internals and find a way to do this, but my intention is to apply few checks before running the `y` (and `x`) argument through `eval`:
1. Is `numexpr` installed - to avoid the build fail
2. Is this a valid expression that eval can handle
3. Is there a column name with the same label
4. Deal with multicolumn selection (["a","b"])

In case these checks fail, it will fall back to the default non-expr plot.

I personally use `query` and `eval` a lot in my routine analysis and I find it to be one of the best parts of `pandas`. Combine this with plotting and you'll get something very powerful.

E.g. this oneliner:

`df.plot(y=["a+2*b","a+3*b"])`

replace the following code:

```
df["d"] = df["a"] + 2*df["b"]
df["e"] = df["a"] + 3*df["b"]
df.plot(y=["d","e"])
```

TMHO, the one liner is more clear and natural, and more importantly, it leaves the original `df` unchanged. No need to stack unnecessary columns just for plotting reasons. 

This looks really useful. If not accepted can you put it into a separate package?

I think pydata should pursue more focused local DSL stuff. If I get that we're trying to avoid unfamiliar magic, but there's also a code complexity tradeoff trying to do acrobatics and shoehorn mathy stuff with normal python syntax.

This is a common refrain I hear and agree with.

Just a thought.

I guess the current syntax is a bit akward

```
In [17]: df = pd.DataFrame({"a": [1, 2],"b": [4,5]})

In [18]: df.assign(**{'a+b':df.eval('a+b')}).plot('a','a+b')
Out[18]: <matplotlib.axes._subplots.AxesSubplot at 0x112da0790>
```

This also came up in the discussion around labeled-data support in matplotlib.  We elected to not support it (at least to start) for exactly the reasons that @TomAugspurger listed above. 

OK, I've used the `assign` method @jreback has suggested so now it supports list of mixed numerical expressions and existing columns.

See updated example notebook [here](http://nbviewer.jupyter.org/gist/TsvikiHirsh/11acb5f821bb1257b5fe)

In case there is a conflict between an existing column name and a given numerical expression, the existing column is shown in the plot.

It might worth to think of opting a new option in `df.plot`, e.g. `eval = True` which enable evaluating numerical expressions.

Another enhancement I would like to addinsome point, is to support `query` via expressions like `a > 0` which currently only plots True or False values from `eval`.

I understand your concerns, and I want to believe that in this case the applicability and simplisity of this feature would help to make it happen.

@TsvikiHirsh so I would be ok with this as an example in the cookbook. will repurpose to that. pls re-open if you'd like to update.

We had a second request for this. From https://github.com/pydata/pandas/issues/13537#issuecomment-229863248

> I am coming from ROOT where this feature is very common with TTree::Draw. In physics this is very common. Suppose I have a three columns with the position of a point ('x', 'y', 'z') and one with the the time, I want to plot the distance from the origin:
> 
> ```
> df.plot.scatter(x='time', y='sqrt(x**2 + y**2 + z**2)')
> ```

I'm coming around on this a bit, it could be very convenient for interactive work.

@TsvikiHirsh did you post your implementation anywhere? How much work was it to add?

No unfortunately I couldn't find time for this. 
It is not hard since the mechanisms already exist in eval and co.
The only problems were to make it work for all plot kinds and to make sure to fall back to default when the expression equals one of the column names.
See my second implementation above.
I will be happy to help with this in my time limitations