FiofanS FiofanS - 1 month ago 4
R Question

How to put together two filled area plots?

I have two data frames:

dput(df1)

structure(list(month = structure(1:12, .Label = c("Jan", "Feb",
"Mar", "Apr", "May", "Jun", "Jul", "Ago", "Sep",
"Oct", "Nov", "Dec"), class = c("ordered", "factor"
)), max_wt_per_month = c(145.433333333333, 103, 111.916666666667,
190.85, 154.683333333333, 136.066666666667, 168.533333333333,
94.2666666666667, 180, 146.233333333333, 157.4, 179.933333333333
), min_wt_per_month = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.05
), avg_wt_per_month = c(8.62182932965783, 8.6232935986297, 10.0719732082026,
10.0015567184692, 14.7826000421388, 12.4903419254567, 15.2629113635624,
15.2463245173283, 14.1524047780697, 7.89863122852994, 6.61470640814081,
8.39703918722787)), .Names = c("month", "max_wt_per_month", "min_wt_per_month",
"avg_wt_per_month"), row.names = c(5L, 4L, 9L, 1L, 8L, 7L, 6L,
2L, 12L, 11L, 10L, 3L), class = "data.frame")


and

dput(df2)

structure(list(month = structure(1:12, .Label = c("Jan", "Feb",
"Mar", "Apr", "May", "Jun", "Jul", "Ago", "Sep",
"Oct", "Nov", "Dec"), class = c("ordered", "factor"
)), max_wt_per_month = c(113.2, 96.3833333333333, 109.433333333333,
176.933333333333, 151.333333333333, 122.233333333333, 174.583333333333,
96.65, 192.05, 164.483333333333, 170.966666666667, 192.883333333333
), min_wt_per_month = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
avg_wt_per_month = c(17.6627541466025, 16.6349269588313,
21.1785870516185, 20.4826873385013, 26.466982862202, 21.9996887643946,
28.8988648947951, 31.9911411411411, 30.0452008346375, 17.4505074160812,
17.3421645263354, 21.4158029053789)), .Names = c("month",
"max_wt_per_month", "min_wt_per_month", "avg_wt_per_month"), row.names = c(5L,
4L, 9L, 1L, 8L, 7L, 6L, 2L, 12L, 11L, 10L, 3L), class = "data.frame")


I want to create a filled area plot as shown here (the one is called "Interior Filling for Area Chart"). I can plot
df1
and
df2
separately, however I cannot put them together on a single plot. How to do it?

This is my current code:

library(plotly)

plot_ly(df1, x = ~month, y = ~max_wt_per_month, type = 'scatter', mode = 'lines',
line = list(color = 'rgba(0,100,80,1)'),
showlegend = FALSE, name = 'Max, 1') %>%
add_trace(y = ~min_wt_per_month, type = 'scatter', mode = 'lines',
fill = 'tonexty', fillcolor='rgba(0,100,80,0.2)', line = list(color = 'rgba(0,100,80,1)'),
showlegend = FALSE, name = 'Min, 1') %>%

plot_ly(df2, x = ~month, y = ~max_wt_per_month, type = 'scatter', mode = 'lines',
line = list(color = 'rgba(168, 216, 234, 1)'),
showlegend = FALSE, name = 'Max, 2') %>%
add_trace(y = ~min_wt_per_month, type = 'scatter', mode = 'lines',
fill = 'tonexty', fillcolor='rgba(168, 216, 234, 1)', line = list(color = 'rgba(168, 216, 234, 1)'),
showlegend = FALSE, name = 'Min, 2') %>%

layout(title = "...",
paper_bgcolor='rgb(255,255,255)', plot_bgcolor='rgb(229,229,229)',
xaxis = list(title = "months",
gridcolor = 'rgb(255,255,255)',
showgrid = TRUE,
showline = FALSE,
showticklabels = TRUE,
tickcolor = 'rgb(127,127,127)',
ticks = 'outside',
zeroline = FALSE),
yaxis = list(title = "wt",
gridcolor = 'rgb(255,255,255)',
showgrid = TRUE,
showline = FALSE,
showticklabels = TRUE,
tickcolor = 'rgb(127,127,127)',
ticks = 'outside',
zeroline = FALSE))


It gives me an error:

Error: First argument,
data
, must be a data frame.


I checked that
class(df1)
and
class(df2)
return
data.frame
. So, don't really understand this message.

The expected result is something similar to this one.

Update 1:

I tried to use
ggplot2
with the following modifications in the data structure (but in this case the chart looks like a bar chart (with very thin bars), not filled area chart):

df1$type = "1"
df2$type = "2"

data_merged = rbind(df1,df2)

library(ggplot2)

ggplot(data_merged, aes(x=month, y=max_wt_per_month, fill=as.factor(type))) +
+ geom_area(colour="black", size=.2, alpha=.4) +
+ scale_fill_brewer(palette="Greens", breaks=rev(levels(as.factor(data_merged$type))))


Update 2:

I have just realized that
ggplot2
works if I substitute month names with numbers, but how can I mantain month names??

Answer

You are trying to "pipe" your first plot into your second one (so basically trying to pass a class plotly_hash instead of a data.frame). Simply replace your second plot_ly() call by add_trace() and specify data = df2. You also need to specify x = ~month in your add_trace()s calls and use fill = 'tonextx' instead of fill = 'tonexty'.

library(plotly)

plot_ly(df1, x = ~month, y = ~max_wt_per_month, 
        type = 'scatter', mode = 'lines',
        line = list(color = 'rgba(0,100,80,1)'),
        showlegend = FALSE, name = 'Max, 1') %>%
  add_trace(x = ~month,
            y = ~min_wt_per_month, 
            type = 'scatter', mode = 'lines',
            fill = 'tonextx',
            fillcolor='rgba(0,100,80,0.2)', 
            line = list(color = 'rgba(0,100,80,1)'),
            showlegend = FALSE, name = 'Min, 1') %>%
  add_trace(x = ~month, 
            y = ~max_wt_per_month, 
            type = 'scatter', mode = 'lines',
            line = list(color = 'rgba(168, 216, 234, 1)'),
            showlegend = FALSE, name = 'Max, 2', data = df2) %>%
  add_trace(x = ~month,
            y = ~min_wt_per_month, 
            type = 'scatter', mode = 'lines',
            fill = 'tonextx', 
            fillcolor='rgba(168, 216, 234, 1)', 
            line = list(color = 'rgba(168, 216, 234, 1)'),
            showlegend = FALSE, name = 'Min, 2', data = df2) %>%
  layout(title = "...",
         paper_bgcolor = 'rgb(255,255,255)', 
         plot_bgcolor='rgb(229,229,229)',
         xaxis = list(title = "months",
                      gridcolor = 'rgb(255,255,255)',
                      showgrid = TRUE,
                      showline = FALSE,
                      showticklabels = TRUE,
                      tickcolor = 'rgb(127,127,127)',
                      ticks = 'outside',
                      zeroline = FALSE),
         yaxis = list(title = "wt",
                      gridcolor = 'rgb(255,255,255)',
                      showgrid = TRUE,
                      showline = FALSE,
                      showticklabels = TRUE,
                      tickcolor = 'rgb(127,127,127)',
                      ticks = 'outside',
                      zeroline = FALSE))

Which gives:

enter image description here

Comments