简体   繁体   English

如何在plotly.js中按周对值进行分组

[英]How to group values by week in plotly.js

Seen below is a time series bar graph with a range selector in plotly.js. 下面显示的是在plotly.js中具有范围选择器的时间序列条形图。

In it, I am trying to figure out how to group the values by week, but cannot seem to accomplish this. 在其中,我试图找出如何按周对值进行分组,但似乎无法实现这一点。 Is there a setting in plotly.js to group these by week when changing the time range selection? 更改时间范围选择时,plotly.js中是否有设置按周将其分组? I cannot seem to figure out if it is possible. 我似乎无法弄清楚是否有可能。

Here are the main documentation pages they offer, of which I tried as many settings as I thought pertained to accomplishing this, but could not figure it out. 这是他们提供的主要文档页面,我尝试了许多与完成此操作有关的设置,但无法弄清楚。

 var days = (function(start,count){ var days = []; var MSday = 1000 * 60 * 60 * 24; for(var i = 0; i < count; i++){ days.push(new Date(+start + i*MSday)); } return days; })(new Date(2018,0,1),100); function vals(){ var vals = []; for(var i = 0; i < 100; i++){ vals.push((Math.random() * 2 * i) | 0); } return vals; } var selectorOptions = { buttons: [{ step: 'month', stepmode: 'backward', count: 1, label: '1m' }, { step: 'month', stepmode: 'backward', count: 6, label: '6m' }, { step: 'year', stepmode: 'todate', count: 1, label: 'YTD' }, { step: 'year', stepmode: 'backward', count: 1, label: '1y' }, { step: 'all', }], }; var trace1 = { x: days, y: vals(), type: 'bar', name: 'Trace 1' }; var trace2 = { x: days, y: vals(), type: 'bar', name: 'Trace 2' }; var data = [trace1, trace2]; var layout = { title: 'Bar Demo', barmode: 'group', xaxis: { rangeselector: selectorOptions } }; Plotly.newPlot('myDiv', data, layout); 
 <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> <div id="myDiv"><!-- Plotly chart will be drawn inside this DIV --></div> 

How can I make the 6 month selection group by week instead of by day on the graph? 如何在图表上按周而不是按天进行6个月选择分组?

Apparently this isn't built in. If it is, or becomes built in at some point, please indicate that here in a comment or another answer. 显然这不是内置的。如果是内置的,或在某个时候内置的,请在评论或其他答案中指出。

The only option I was able to determine as viable was to hook into the relayout event using .on('plotly_relayout', function () { , taking the arguments from the range selector buttons (which seem limited, only a from and to date, if there is a better way to determine the origination please also let me know and I will update here), and then roughly based on that to bin the dates by week and adjust the x and y values in the plot. 我唯一确定可行的选择是使用.on('plotly_relayout', function () { ,从范围选择器按钮中获取参数(似乎是有限的,仅是from和date,如果有更好的方法来确定来源,也请让我知道,我将在此处进行更新),然后大致基于此来按周对日期进行分类,并调整绘图中的x和y值。

This is just a basic implementation as proof of concept. 这只是作为概念证明的基本实现。 Using it in production would require refactoring this code to work with the existing data structures with regards to design and page implementation. 在生产中使用它需要重构此代码以在设计和页面实现方面与现有数据结构一起使用。

There is a lot going on here. 这里有很多事情。 Basically, it will iterate through the set of dates to create sunday bins which will hold the weekly data (note that it still lacks a display update to show it is a week from the start date). 基本上,它将遍历日期集以创建将包含每周数据的星期天框(请注意,它仍然缺少显示更新以显示它是从开始日期开始的一周)。 Once it has the bins it sums the dates in each bin range. 一旦有了垃圾箱,它将对每个垃圾箱范围内的日期进行求和。 Then it replaces the data set using restyle . 然后使用restyle替换数据集。 If the range selected is not 6m then it will use the a slice of the backup data because plotly modifies arrays in place, and as a result it will overwrite the data if there is no backup copy in addition with a single copy every time the backup is used. 如果选择的范围不是6m,则它将使用一部分备份数据,因为会按计划修改阵列,因此,如果没有备份副本,则每次备份时都会覆盖一个副本,因此它将覆盖数据。用来。

See below for a working demo. 请参见下面的工作演示。

 function sum(array){ return array.reduce(function(sum,curr){ return sum + curr; },0); }; Date.MSday = 1000 * 60 * 60 * 24; Date.prototype.floor = function(){ return new Date(this.getFullYear(),this.getMonth(),this.getDate()); } Date.prototype.addDays = function(days){ var time = +this - +this.floor(); var addedDays = new Date(+this.floor() + Date.MSday*days); return new Date(+addedDays + time); } function weeksFromDates(datesArray, valsArray){ var lastDay = datesArray[datesArray.length -1]; var firstDay = datesArray[0]; var dayOfWeek = firstDay.getDay(); var firstSunday = firstDay.addDays(-dayOfWeek); var sundays = []; var currentSunday = firstSunday; while(currentSunday < lastDay){ sundays.push(currentSunday); currentSunday = currentSunday.addDays(7); } currentSunday = currentSunday.addDays(7); sundays.push(currentSunday); var valSets = []; var n = 0; for(var i = 1; i < sundays.length; i++){ var last = sundays[i-1]; var next = sundays[i]; var theseVals = []; for(; n < datesArray.length && last <= datesArray[n] && next > datesArray[n]; n++){ theseVals.push(valsArray[n]); } valSets.push(sum(theseVals)); } sundays.pop(); return {x: sundays, y: valSets}; } var MSday = 1000 * 60 * 60 * 24; var days = (function(start,count){ var days = []; for(var i = 0; i < count; i++){ days.push(new Date(+start + i*MSday)); } return days; })(new Date(2018,0,1),100); function vals(){ var vals = []; for(var i = 0; i < 100; i++){ vals.push((Math.random() * 2 * i) | 0); } return vals; } var selectorOptions = { buttons: [{ step: 'month', stepmode: 'backward', count: 1, label: '1m' }, { step: 'month', stepmode: 'backward', count: 6, label: '6m' }, { step: 'year', stepmode: 'todate', count: 1, label: 'YTD' }, { step: 'year', stepmode: 'backward', count: 1, label: '1y' }, { step: 'all', }], }; var trace1 = { x: days, y: vals(), type: 'bar', name: 'Trace 1', orientation: 'v' }; var trace2 = { x: days, y: vals(), type: 'bar', name: 'Trace 2', orientation: 'v' }; var data = [trace1, trace2]; var dataBackup = $.extend(true,{},data); var layout = { title: 'Bar Demo', barmode: 'group', xaxis: { rangeselector: selectorOptions } }; Plotly.newPlot('myDiv', data, layout); $('#myDiv').on('plotly_relayout', function () { var lower = new Date(arguments[1]['xaxis.range[0]']); var upper = new Date(arguments[1]['xaxis.range[1]']); var dayRange = (+upper - +lower) / MSday; if( dayRange < 190 && dayRange > 170 ){ //6m for(var n = 0; n < data.length; n++){ var weekly = weeksFromDates(dataBackup[n].x,dataBackup[n].y); Plotly.restyle('myDiv',{x:[weekly.x],y: [weekly.y]},n); } }else{ for(var n = 0; n < data.length; n++){ Plotly.restyle('myDiv',{x:[dataBackup[n].x.slice()],y: [dataBackup[n].y.slice()]},n); } } }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> <div id="myDiv"><!-- Plotly chart will be drawn inside this DIV --></div> 

Blimey! 天哪! There is a much simpler option... 有一个更简单的选择...

use 7 days: 使用7天:

    step: 'day',
    stepmode: 'backward',
    count: 7,
    label: '1w'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM