在曲线R

时间:2017-11-03 00:09:51

标签: r plotly r-plotly

这篇文章 - Set marker size in plotly - 遗憾的是没有帮助我正在寻找的东西,而且是我能找到的唯一主题。根据散点图的尺寸参数的图表文档:

“size(数字或数字大于或等于0的数组),默认值:6,设置标记大小(以px为单位)”

(在px中)对我来说是一个问题。我想创建一个图表,其中标记大小基于坐标值,而不是像素,这样我可以增加图形的大小(例如,通过完全筛选),并且点的大小也会增加。我目前的代码示例:

library(plotly)
mydf <- data.frame(x = rep(1:20, times = 20), y = rep(1:20, each = 20),
                   thesize = 10)
plot_ly(mydf) %>%
  add_trace(x = ~x, y = ~y, type = 'scatter', mode = 'markers', 
            marker = list(symbol = 'hexagon', size = ~thesize, opacity = 0.6))

如果您在R中创建此绘图,然后通过拖动Rstudio查看器窗口或其他方式使绘图更大或更小,您会注意到标记保持完全相同的大小(10像素),这令人沮丧。如果我能让这些标记的直径== 1(在x轴上),而不是设置为像素数,我会喜欢它。这可能吗?

任何帮助都非常感谢!!!

1 个答案:

答案 0 :(得分:2)

  • 让我们从定义轴范围的图开始。

    p <- plot_ly() %>% layout(xaxis = list(range = c(1, 5)))
    
  • 现在添加一个JavaScript eventlistener,它捕获绘图布局中的任何变化

    javascript <- "
    var myPlot = document.getElementsByClassName('plotly')[0];
    
    function resize(eventdata) {
      // magic happens here
    }
    
    myPlot.on('plotly_relayout', function(eventdata) {
      resize(eventdata);
    });
    "
    p <- htmlwidgets::prependContent(p, 
                                     onStaticRenderComplete(javascript))
    p
    
  • 事件从我们可以获取新轴范围的eventdata开始。

    eventdata['xaxis.range[1]']
    
  • 由于我们事先并不知道地块的大小,我们通过轴线的大小确定它

    var plot_width = Plotly.d3.select('.xlines-above').node().getBBox()['width'];
    
  • 我们需要手动调用一次事件以确保图表已正确初始化

初始情节 Before zooming

放大

enter image description here 完整的R代码

library("plotly")
library("htmlwidgets")

p <- plot_ly() %>%
  add_trace(x = c(1.5, 3, 4.2),
            y = c(-2, 1, 2), 
            type = 'scatter',
            mode = 'lines+markers',
            showlegend = F) %>% 
  add_trace(x = c(2, 3, 4.2),
            y = c(2, 0, -1),
            type = 'scatter',
            mode = 'lines+markers',
            showlegend = F) %>%
  add_trace(x = c(1.5, 3, 4.2),
            y = c(1, 0.5, 1),
            type = 'scatter',
            mode = 'markers',
            showlegend = F) %>% 
  layout(xaxis = list(range = c(1, 5)))
javascript <- "
marker_size = 0.5; // x-axis units
var myPlot = document.getElementsByClassName('plotly')[0];

function resize(eventdata) {
  var xaxis_stop = 5;
  var xaxis_start = 1;
  var plot_width = Plotly.d3.select('.xlines-above').node().getBBox()['width'];
  if (eventdata['xaxis.range[1]'] !== undefined) {
    var update = {'marker.size': marker_size * plot_width / (eventdata['xaxis.range[1]'] - eventdata['xaxis.range[0]'])};
  } else {
    var update = {'marker.size': marker_size * plot_width / (xaxis_stop - xaxis_start)};
  }
  Plotly.restyle(myPlot, update, 2);
}
resize({eventdata: {}});

myPlot.on('plotly_relayout', function(eventdata) {
  resize(eventdata);
});
"
p <- htmlwidgets::prependContent(p, 
                                 onStaticRenderComplete(javascript))
p

互动JavaScript示例

  • 您可以从图形的定义高度/宽度和定义的轴范围开始,这样您就可以知道一个轴单位有多少像素。
  • 标记的大小最初将是您想要的大小。
  • 每当用户更改轴范围时,系统都会触发plotly_relayout事件,您可以从eventdata(开始)和xaxis.range[1]中的xaxis.range[1]检索新范围(端部)
  • 根据新范围,您可以relayout标记尺寸。

&#13;
&#13;
var plot_width = 500;
var plot_height = 500;
var margin_l = 100;
var margin_r = 100;
marker_size = 0.5; // x-axis units
xaxis_start = 1;
xaxis_stop = 5;

var trace1 = {
  x: [1.5, 2, 3, 4],
  y: [10, 15, 13, 17],
  mode: "markers",
  marker: {
    size: marker_size *
      (plot_width - margin_l - margin_r) /
      (xaxis_stop - xaxis_start)
  },
  showlegend: false
};

var trace2 = {
  x: [2, 3, 4, 4.5],
  y: [16, 5, 11, 10],
  mode: "lines"
};

var trace3 = {
  x: [1.5, 2, 3, 4],
  y: [12, 9, 15, 12],
  mode: "lines+markers",
  showlegend: false
};

var data = [trace1, trace2, trace3];

var layout = {
  width: plot_width,
  height: plot_height,
  margin: {
    l: margin_l,
    r: margin_r
  },
  xaxis: {
    range: [1, 5]
  },
  showlegend: false
};

Plotly.newPlot("myDiv", data, layout);

var refplot = document.getElementById("myDiv");
refplot.on("plotly_relayout", function(eventdata) {
  if (eventdata["xaxis.range[1]"] !== undefined) {
    var update = {
      "marker.size": marker_size *
        (plot_width - margin_l - margin_r) /
        (eventdata["xaxis.range[1]"] - eventdata["xaxis.range[0]"])
    };
  } else {
    var update = {
      "marker.size": marker_size *
        (plot_width - margin_l - margin_r) /
        (xaxis_stop - xaxis_start)
    };
  }
  Plotly.restyle("myDiv", update, 0);
});
&#13;
<head>
  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>

<body>
  <div id="myDiv"></div>
</body>
&#13;
&#13;
&#13;