export function combineDatasets()

in src/utils/Data.js [210:261]


export function combineDatasets(datasetsInfo = [], combineKey = 'x') {
  // combineDatasets combines multiple datasets into one, joined on a common key 'combineKey'
  // datasetsInfo is an array that looks like:
  // [
  //   {data: [{x: 0, y: 3}, ...], combineKey: 'x', dataKeys: {y: 'y0'}}
  //   {data: [{count: 0, value: 4}], combineKey: 'count', dataKeys: {value: 'y1'}}
  // ]
  // where `data` is an array of data points of any shape
  // `combineKey` is the key for the value which the datasets are joined on
  // `dataKeys` are getters for other values in each datapoint which should be merged into the combined dataset
  //   - key = getter in original datapoint, value = setter for combined dataset
  // example above (with default combinedKey) results in:
  // [{x: 0, y0: 3, y1: 4}, ...]

  // index each dataset by its combineKey values so we can quickly lookup if it has data for a given value
  const datasetLookups = datasetsInfo.map(datasetInfo => {
    const { data } = datasetInfo;
    return keyBy(data, datasetInfo.combineKey || combineKey);
  });

  // Grab combineKey from each dataset and flatten into one array
  const allCombineValues = [].concat(
    ...datasetsInfo.map(datasetInfo =>
      datasetInfo.data.map(makeAccessor(datasetInfo.combineKey || combineKey)),
    ),
  );

  // Get all unique values
  const uniqueValues = uniqBy(allCombineValues, value => {
    return value instanceof Date ? value.toString() : value;
  });

  // For each of the unique combineKey data values, go through each dataset and look for a combineKey value that matches
  // if we find it, combine the values for that datum's dataKeys into the final combinedDatum object
  return uniqueValues.map(combineValue => {
    const combinedDatum = { [combineKey]: combineValue };

    datasetsInfo.forEach((datasetInfo, datasetIndex) => {
      if (!datasetInfo.dataKeys || !Object.keys(datasetInfo.dataKeys).length)
        return;
      const datasetLookup = datasetLookups[datasetIndex];
      if (!has(datasetLookup, combineValue)) return;

      const datum = datasetLookup[combineValue];
      forEach(datasetInfo.dataKeys, (newDataKey, originalDataKey) => {
        combinedDatum[newDataKey] = datum[originalDataKey];
      });
    });

    return combinedDatum;
  });
}