# Grid plot by factors with Dataframes and Plots

**URL:** <https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454>\
**Category:** General Usage\
**Tags:** plotting\
**Created:** [April 20, 2018, 12:56pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454 "2018-04-20T12:56:28Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [April 20, 2018, 12:56pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454/1 "2018-04-20T12:56:29Z")

</div>

I have a Dataframe with two factors, an IV and a DV. I want to create a grid of plots based on the two factors using Plots.jl. Here is a minimum working example of the data format:

```julia
using DataFrames 
df = DataFrame()
df[:Factor1] = repeat(repeat(1:2,inner=5),inner=10)
df[:Factor2] = repeat(repeat(1:2,outer=5),inner=10)
df[:IV] = rand(100)
df[:DV] = rand(100)

```

I see there is a group argument, but that creates multiple plots within the same plot. Is there a clever way to create a grid of plots from this data?

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [April 20, 2018, 1:36pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454/2 "2018-04-20T13:36:29Z")

</div>

If your factors go from `1` to `M` and `1` to `N` respectively, the simplest would be:

```julia
using StatPlots, DataFrames
@df df scatter(:IV, :DV, group = {:Factor1, :Factor2}, layout = (M, N))

```

For more complex situation I would have thought the following would work and be useful:

```julia
plot(layout = (M,N))
by(df, [:Factor1, :Factor2]) do dd
    @df dd scatter!(:IV, :DV, subplot = (:Factor1, :Factor2))
end

```

But fails for technical reasons. Somehow a `SubDataFrame` does not have the `IterableTables` implementation and our plotting macro can’t handle it, I’ll file an issue.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [April 20, 2018, 1:43pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454/3 "2018-04-20T13:43:06Z")

</div>

Thanks!

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [April 20, 2018, 2:10pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454/4 "2018-04-20T14:10:14Z")

</div>

Do you have a recommendation for setting the sub-titles? For example, the first title would be “1 1”, the second “1 2” etc? As far as I can tell, it does not seem possible without creating the subplots in a loop, which does not work currently.

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [April 20, 2018, 2:37pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454/5 "2018-04-20T14:37:21Z")

</div>

I’m actually not sure how one would go about that. The only thing I can think of is that you can pass the titles as a row array (say `title = ["a" "b" "c" "d"]` to pass it to all subplots), but you’d need to compute that array by hand.

If you do a lot of these plots with grouped data you may consider [GroupedErrors](https://github.com/piever/GroupedErrors.jl) which has a `@set_attr` macro to set attributes that depend on a value of the grouping variables (we should maybe add something similar to Plots). For example:

```julia
using Plots, GroupedErrors
@> df begin
       @splitby (_.Factor1, _.Factor2)
       @x _.IV
       @y _.DV
       @set_attr :title string(_[1], " ", _[2])
       @plot scatter(layout = (2,2), legend = false)
end

```

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [April 20, 2018, 3:48pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454/6 "2018-04-20T15:48:33Z")

</div>

Thanks, I ended up doing something similar but perhaps not very elegant. I created a nested for loop and created sub-DataFrames and added the subplots iteratively. I used ` title = string(factor1Value," ",factor2Value)` to set the title. Perhaps one way set the titles is to use something like `title = (:factor1,:factor2)`. I guess it wouldn’t be a general solution but it would show the factor values in the title of each subplot.

I also encountered a different but not entirely off-topic issue. In actuality, each subplot has two lines, one for a model prediction and one for the data. The legend contains a separate reference for each line ( a total of 8), but I only want two generic references, one for the model and one for the data. As far as I can tell there is no way to modify the legend with a function such as `legend!([model,data],[:red,:black])`. Do you think it would be worth while to file an issue for a feature like this?

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [April 20, 2018, 4:33pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454/7 "2018-04-20T16:33:00Z")

</div>

`legend` is used to set legend position (or legend existence), `label` is the attribute used to determine what appears on the legend labels.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [April 20, 2018, 4:56pm UTC](https://discourse.julialang.org/t/grid-plot-by-factors-with-dataframes-and-plots/10454/8 "2018-04-20T16:56:49Z")

</div>

Ok. I see. I think the same problem persists. The attached plot shows that it the legend contains duplicate entries. Without something like `label!()`, it does not appear there is a way to remove the duplicates.

![19%20PM](https://global.discourse-cdn.com/julialang/original/3X/2/0/2041643bc462ac49a2519350aa8a5c41a208b2cf.png)
