Add vertical line to line chart in rChart NVD3 (nPlot)

倾然丶 夕夏残阳落幕 提交于 2019-12-11 09:56:00

问题


I would like to add several vertical lines indicating particular events in a line chart created with nPlot. Any suggestions?

library(reshape2)
library(ggplot2)
library(rCharts)

ecm <- reshape2::melt(economics[,c('date', 'uempmed', 'psavert')], id = 'date')

p7 <- nPlot(value ~ date, group = 'variable', data = ecm, type = 'lineWithFocusChart')

Final goal: add vertical lines with labels at 'date' = '1967-11-30', '2001-11-30', '1968-01-31', etc.


回答1:


Ok, so this should answer the question. I think you will notice that this is generally considered well beyond the skill level of an average R user. Eventually, it would be nice to write a custom chart to handle this behavior well and make easy and available to the general R user. I would like to generalize both the dashed and the vertical lines to handle in R. Here is the rCharts viewer demo and the live code example.

library(reshape2)
library(ggplot2)
library(rCharts)

ecm <- reshape2::melt(economics[,c('date', 'uempmed', 'psavert')], id = 'date')
p7 <- nPlot(value ~ date, group = 'variable', data = ecm, type = 'lineWithFocusChart')

#let's add this to make date handling easier
p7$xAxis( tickFormat="#!function(d) {return d3.time.format('%b %Y')(new Date( d * 86400000 ));}!#" )


#grab template from
#https://github.com/ramnathv/rCharts/blob/master/inst/libraries/nvd3/layouts/chart.html
#modify to add callback on graph render

p7$setTemplate(script = sprintf("
  <script type='text/javascript'>
    $(document).ready(function(){
      draw{{chartId}}(  );
    });
  function draw{{chartId}}(  ){  
    var opts = {{{ opts }}};
    var data = {{{ data }}};

    if(!(opts.type==='pieChart' || opts.type==='sparklinePlus' || opts.type==='bulletChart')) {
      var data = d3.nest()
      .key(function(d){
        //return opts.group === undefined ? 'main' : d[opts.group]
        //instead of main would think a better default is opts.x
        return opts.group === undefined ? opts.y : d[opts.group];
      })
      .entries(data);
    }

    if (opts.disabled != undefined){
      data.map(function(d, i){
        d.disabled = opts.disabled[i]
      })
    }

    nv.addGraph(function() {
      chart = nv.models[opts.type]()
      .width(opts.width)
      .height(opts.height)

      if (opts.type != 'bulletChart'){
        chart
        .x(function(d) { return d[opts.x] })
        .y(function(d) { return d[opts.y] })
      }


{{{ chart }}}

{{{ xAxis }}}

{{{ x2Axis }}}

{{{ yAxis }}}

d3.select('#' + opts.id)
.append('svg')
.datum(data)
.transition().duration(500)
.call(chart);

chart.dispatch.brush.on('brushstart',function(){ drawVerticalLines( opts ) });
chart.dispatch.brush.on(
  'brushend',
  function(){ window.setTimeout(
    function() {drawVerticalLines( opts )},
    250
  )}
);

nv.utils.windowResize(chart.update);
return chart;
    },%s);
  };

%s
</script>
"
,
#here is where you can type your vertical line/label function
"function() { drawVerticalLines( opts ) }"
,
#add the afterScript here if using with shiny
"
    function drawVerticalLines( opts ){

  if (!(d3.select('#' + opts.id  + ' .nvd3 .nv-focus .nv-linesWrap').select('.vertical-lines')[0][0])) {
   d3.select('#' + opts.id  + ' .nvd3 .nv-focus .nv-linesWrap').append('g') 
      .attr('class', 'vertical-lines')
  }

  vertLines = d3.select('#' + opts.id  + ' .nvd3 .nv-focus .nv-linesWrap').select('.vertical-lines').selectAll('.vertical-line')
                  .data(
                    [ 
                      { 'date' : new Date('1967-11-30'),
                        'label' : 'something to highlight 1967'
                      } ,
                      { 'date' : new Date('2001-11-30'),
                        'label' : 'something to highlight 2001'
                      }
                    ] )

  var vertG = vertLines.enter()
    .append('g')
    .attr('class', 'vertical-line')

  vertG.append('svg:line')
  vertG.append('text')

  vertLines.exit().remove()

  vertLines.selectAll('line')
      .attr('x1', function(d){
         return chart.xAxis.scale()(d.date/60/60/24/1000)
      })
      .attr('x2', function(d){ return chart.xAxis.scale()(d.date/60/60/24/1000) })
      .attr('y1', chart.yAxis.scale().range()[0] )
      .attr('y2', chart.yAxis.scale().range()[1] )
      .style('stroke', 'red')

  vertLines.selectAll('text')
      .text( function(d) { return d.label })
      .attr('dy', '1em')
      //x placement ; change dy above for minor adjustments but mainly
      //    change the d.date/60/60/24/1000 
      //y placement ; change 2 to where you want vertical placement
      //rotate -90 but feel free to change to what you would like
      .attr('transform', function(d){
         return  'translate(' +
          chart.xAxis.scale()(d.date/60/60/24/1000) + 
          ',' + 
          chart.yAxis.scale()(2) +
          ') rotate(-90)'
      })
      //also you can style however you would like
      //here is an example changing the font size
      .style('font-size','80%')

}
"
))


p7

Let me know your thoughts.



来源:https://stackoverflow.com/questions/24944151/add-vertical-line-to-line-chart-in-rchart-nvd3-nplot

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!