Skip to content
This repository has been archived by the owner on Feb 19, 2022. It is now read-only.

VictoryBoxPlot #557

Merged
merged 28 commits into from
Mar 27, 2018
Merged

VictoryBoxPlot #557

merged 28 commits into from
Mar 27, 2018

Conversation

parkerziegler
Copy link

@boygirl Sorry this is coming in late – I had an epiphany as I went to start this PR on Friday and wanted to get in some changes.

Purpose

This PR contains initial work for a VictoryBoxPlot component to be introduced into victory-chart. This component uses primitives created in victory-core on the branch of the same name (feature/victory-boxplot). To get it running, you'll need to follow the lank workflow using the branch of the same name from victory-core. This component is functional but by no means complete. More work needs to be done to ensure it conforms to standards for other components in victory-chart. Tests also need to be written for this component. This branch should not be merged in its current state.

Component Structure

To see how this component is being used, check out victory-boxplot-demo.js.

VictoryBoxPlot

This PR introduces two new files to the library – victory-boxplot.js and helper-methods.js under src/components/victory-boxplot.

Working with Data

The VictoryBoxPlot component accepts data in three formats at this time.

  • The standard form i.e. data={[{ x: 1, y: 3 }, { x: 1, y: 5 }, { x: 1, y: 10 }]} etc. When received in this form, we make certain assumptions about the data:
    • One of the axes of the data has repeat x or y values. For example, we would not handle data in this format if it was passed like so data={[{ x: 1, y: 3 }, { x: 2, y: 5 }, { x: 3, y: 10 }]}. Future work could handle grouping entries by their independent variable value automatically.
    • To determine which value to expect as repeat (x or y), the component requires a horizontal prop of type boolean. When set to true, the component will expect repeat y values and render the box plot horizontally (with min on the left and max on the right). The default value for horizontal is false.
  • With the dependent variable as an array, i.e. data={[{ x: 1, y: [2, 3, 5] }, { x: 1, y: [3, 5, 7, 8] }, { x: 1, y: [5, 10, 25, 32 }]}.
    • When received in this way, we treat each datum as corresponding to a separate box plot, i.e. the above example would render three separate box plots.
  • As an already processed set of quartile variables, i.e. data={[{ min: 1, max: 10, q1: 2.5, q3: 6, med: 5 }]}. If an array of objects of the above form is passed, a separate box plot will be rendered for each.

Processing Data

In order to accept the data in all of the above forms, we run the data through a set of methods to determine how to process it. These are all available in helper-methods.js and should be checked for efficiency and efficacy. The current checks we have in place:

  • Determine if data is passed in the pre-processed format – this.checkProcessedData.
    • This method invokes this.checkHasQuartileAttributes to ensure that all necessary quartile attributes (min, max, q1, q3, and med) are present on the datum.
    • This method also invokes this.checkHasDistinctIndependentVariable, which ensures that each datum has a unique x or y attribute (whichever is the independent variable in this case, which is determined using the horizontal prop).
  • If not processed, determine if data contains a dependent variable passed as an array (the second data case mentioned above) – this.checkDependentVariableAsArray.
  • Sort the data if it is not properly sorted. This is necessary to ensure d3's quartile methods work properly.
  • Gather summary statistics on the datumthis.getSummaryStatistics.

Rendering Data

Rendering VictoryBoxPlot is complicated by the fact that there is no single dataComponent for each part of the box plot. Instead, we have the following mapping:

{
  minComponent: <Whisker />,
  maxComponent: <Whisker />,
  q1Component: <Box />,
  q3Component: <Box />,
  medComponent: <Line />
}

This means that the typical this.renderData method in add-events will not work neatly here. Instead, methods are present directly on VictoryBoxPlot that read from the data structure passed and use the data structure keys to clone the correct component. Similarly, in order to clone the correct props for each component (and labels and labelProps) we use the data structure keys. So, each box plot arrives to our render method in the following format:

{
  data: {
    minProps: {},
    maxProps: {},
    q1Props: {},
    q3Props: {},
    medProps: {}
  },
  labels: {
    minLabelProps: {},
    maxLabelProps: {},
    q1LabelProps: {},
    q3LabelProps: {},
    medLabelProps: {}
  }
}

We then call this.getBoxPlotComponent and this.getLabelComponent to obtain the proper component and props for each key. This could almost certainly be done in a more elegant way and I would love to see some improvement in this area.

Getting the Domain for All Box Plots

There is a custom method in helper-methods.js for obtaining the proper x and y domains to contain all box plot datasets passed into data. It takes advantage of the fact that we already have the min and max values for each dataset, and uses these to determine the domain of the dependent axis across all datasets. It obtains the domain of the independent axis as usual.

Suggested Enhancements and Future Work

This component still needs considerable work to behave properly and conform to the standards of other victory-chart components. Some things to direct attention to:

  • Implementing string maps to allow passing string values in the data prop.
  • Using Helpers to allow props like boxWidth and whiskerStyle to accept props as either strings or numbers.
  • Ensuring events and transitions get properly attached to the component. Most of this should be taken care of by add-events but I have not verified.
  • Support for victory-native.
  • More demo examples and tests (currently there are none).
  • Proper passage of labels and use of LabelHelpers.getText - at the moment we are just rendering the computed values for min, max, q1, q3, and med as place holders.
  • Checks on style and layout props like boxWidth, whiskerStyle, and labelOrientation – are these doing what we expect and are there any gotchas?
  • Checks on the current accessor functions for potential improvements.
  • A better way of calculating positioning props using the horizontal prop. Currently, we pass horizontal into nearly every calculation because it dramatically affects positioning. However, there are ternary expressions all over the place that are rapidly inflating the complexity calculations of some methods – and ESLint is not happy about it.
  • Checks on PropTypes and defaultProps.
  • Addition of a displayScatter prop that, when set to true, renders a scatter plot of the raw data on top of the boxplot. Additionally, we may want to add a displayJitter prop that does the same thing but creates a jitter plot by moving the points slightly along the independent axis.

@parkerziegler parkerziegler changed the title Initial work on VictoryBoxPlot WiP: Initial work on VictoryBoxPlot Jan 29, 2018
@adamabeshouse
Copy link

adamabeshouse commented Feb 15, 2018

Hi Parker, I was wondering if you knew approximately what the timeframe for this feature being merged/released might be? We're looking at using it in cbioportal.org but were wondering if it's something we should count on being out soon. Thanks for any response and for your work on this very useful project! -Adam

@parkerziegler
Copy link
Author

parkerziegler commented Feb 16, 2018

@adamabeshouse Thanks for checking in. I know @boygirl is planning to spend some time working on this soon, but is headed on vacation for a few weeks soon. I may get some time to work on it over weekends, but I wouldn't count on it being around imminently – I'm not currently on our OSS team so I have to do these things after hours when I can.

@adamabeshouse
Copy link

Thanks, @parkerziegler!

@boygirl
Copy link
Contributor

boygirl commented Feb 16, 2018

@adamabeshouse this one is next up on my list. I'm on vacation until March 12, but I expect to finish this feature by the end of March at the latest.

@adamabeshouse
Copy link

adamabeshouse commented Feb 16, 2018

Thanks for the information @boygirl ! Enjoy your vacation. - Adam

@boygirl boygirl changed the title WiP: Initial work on VictoryBoxPlot VictoryBoxPlot Mar 27, 2018
@boygirl boygirl merged commit acbe7a0 into master Mar 27, 2018
@boygirl boygirl deleted the feature/victory-boxplot branch March 27, 2018 18:20
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants