16

I'd like to make a horizontal legend below the ggvis chart. I can use legend properties to place it below the chart, but don't know how to make the labels horizontal below the legend title. Below is the minimum reproducible code (grabbed from the web).

df1 = data.frame(x=sample(1:10), y=sample(1:10))
df2 = data.frame(x=1:10, y=1:10)
df3 = data.frame(x=1:10, y=sqrt(1:10))

df2$id <- 1
df3$id <- 2
df4    <- rbind(df2,df3)
df4$id <- factor(df4$id)

df4 %>% ggvis(x=~x, y=~y, stroke=~id) %>% layer_lines() %>%
    # make sure you use add relative scales
    add_relative_scales() %>%
    # values for x and y need to be between 0 and 1
    # e.g for the x-axis 0 is the at far-most left point and 1 at the far-right 
    add_legend("stroke", title="Cylinders",
               properties=legend_props(
                   legend=list(
                       x=scaled_value("x_rel", 0.2),
                       y=scaled_value("y_rel", -.2)
                   ))) %>%
    layer_points(x=~x, y=~y, data=df1, stroke:='black') 
gung - Reinstate Monica
  • 11,583
  • 7
  • 60
  • 79
chungkim271
  • 927
  • 1
  • 10
  • 20
  • 2
    Since this still seems to be an open issue [over at the ggvis GitHub developer page](https://github.com/rstudio/ggvis/issues/409), I doubt this is possible without a major hack. But I could be wrong. – Felix Jan 30 '17 at 09:44
  • @Felix Any idea if this feature has been added to `ggvis` yet? – acylam Sep 05 '17 at 19:18
  • Does my answer seem like what you are looking for? – acylam Sep 05 '17 at 19:25

2 Answers2

0

This is most certainly a hack, but works great:

df4 %>% ggvis(x=~x,y=~y,stroke=~id) %>% layer_lines() %>%
  #make sure you use add relative scales
  add_relative_scales() %>%
  #values for x and y need to be between 0 and 1
  #e.g for the x-axis 0 is the at far-most left point and 1 at the far-right 
  add_legend("stroke", title = "Cylinders", values = c(1, 1),
             properties = legend_props(
               legend = list(
                 x = scaled_value("x_rel", 0.2),
                 y = scaled_value("y_rel", -.2)
               ))) %>%
  add_legend("stroke", title = " ", values = c(2, 2),
             properties = legend_props(
               legend = list(
                 x = scaled_value("x_rel", 0.23),
                 y = scaled_value("y_rel", -.2)
               ))) %>%
  layer_points(x=~x,y=~y,data = df1,stroke:='black') 

enter image description here

Basically, I'm adding another add_legend, setting the title as blank, adjusting the scale_value so that it is very close to the first legend but not overlapping. I then set the first legend with values = c(1,1) and the second with values = c(2,2) so that the two values stack on top of each other. This makes it look like one legend with horizontal values.

acylam
  • 18,231
  • 5
  • 36
  • 45
0

Seen that ggvis is dormant now, maybe you may consider switching to googleVis.

Here's a similar plot you can get by manipulating a little bit your sample data:

df5 <- df4[df4$id==1,]
colnames(df5)[2] <- "y1"

library(tidyverse)

df5 <- df5 %>%
  mutate(
    y0 = df1[order(df1$x),c(2)],
    y2 = sqrt(x)
  )

df5 <- df5[, c(1,4,2,5)]

library(googleVis)

plot_df5 <- gvisLineChart(df5, options=list(
                                            legend="bottom",
                                            series =
                                            "[{labelInLegend: 'Dot', color: 'black'},                                            
                                            {labelInLegend: 'Cylinders: 1', color: 'blue', curveType: 'dot'},
                                            {labelInLegend: 'Cylinders: 2', color: 'orange'}]"
                                           )
                         )
plot(plot_df5)

<!-- LineChart generated in R 3.5.2 by googleVis 0.6.2 package -->
<!-- Sun Dec 30 21:21:26 2018 -->


<!-- jsHeader -->
<script type="text/javascript">


// jsData 
function gvisDataLineChartID1fd8710660d () {
var data = new google.visualization.DataTable();
var datajson =
[
 [
"1",
3,
1,
1
],
[
"2",
4,
2,
1.414213562
],
[
"3",
6,
3,
1.732050808
],
[
"4",
1,
4,
2
],
[
"5",
10,
5,
2.236067977
],
[
"6",
8,
6,
2.449489743
],
[
"7",
7,
7,
2.645751311
],
[
"8",
2,
8,
2.828427125
],
[
"9",
9,
9,
3
],
[
"10",
5,
10,
3.16227766
] 
];
data.addColumn('string','x');
data.addColumn('number','y0');
data.addColumn('number','y1');
data.addColumn('number','y2');
data.addRows(datajson);
return(data);
}


// jsDrawChart
function drawChartLineChartID1fd8710660d() {
var data = gvisDataLineChartID1fd8710660d();
var options = {};
options["allowHtml"] = true;
options["legend"] = "bottom";
options["series"] = [{labelInLegend: 'Dot', color: 'black'},                                            
                                            {labelInLegend: 'Cylinders: 1', color: 'blue', curveType: 'dot'},
                                            {labelInLegend: 'Cylinders: 2', color: 'orange'}];


    var chart = new google.visualization.LineChart(
    document.getElementById('LineChartID1fd8710660d')
    );
    chart.draw(data,options);
    

}
  


// jsDisplayChart
(function() {
var pkgs = window.__gvisPackages = window.__gvisPackages || [];
var callbacks = window.__gvisCallbacks = window.__gvisCallbacks || [];
var chartid = "corechart";
  
// Manually see if chartid is in pkgs (not all browsers support Array.indexOf)
var i, newPackage = true;
for (i = 0; newPackage && i < pkgs.length; i++) {
if (pkgs[i] === chartid)
newPackage = false;
}
if (newPackage)
  pkgs.push(chartid);
  
// Add the drawChart function to the global list of callbacks
callbacks.push(drawChartLineChartID1fd8710660d);
})();
function displayChartLineChartID1fd8710660d() {
  var pkgs = window.__gvisPackages = window.__gvisPackages || [];
  var callbacks = window.__gvisCallbacks = window.__gvisCallbacks || [];
  window.clearTimeout(window.__gvisLoad);
  // The timeout is set to 100 because otherwise the container div we are
  // targeting might not be part of the document yet
  window.__gvisLoad = setTimeout(function() {
  var pkgCount = pkgs.length;
  google.load("visualization", "1", { packages:pkgs, callback: function() {
  if (pkgCount != pkgs.length) {
  // Race condition where another setTimeout call snuck in after us; if
  // that call added a package, we must not shift its callback
  return;
}
while (callbacks.length > 0)
callbacks.shift()();
} });
}, 100);
}


// jsFooter
</script>


<!-- jsChart -->  
<script type="text/javascript" src="https://www.google.com/jsapi?callback=displayChartLineChartID1fd8710660d"></script>


<!-- divChart -->
  
<div id="LineChartID1fd8710660d" 
  style="width: 500; height: automatic;">
</div>
Alessio
  • 910
  • 7
  • 16