Returns formatted data. Data accessors are applied, and string values are replaced.
@param {Array} dataset: the original domain
@param {Object} props: the props object
@param {Array} expectedKeys: an array of expected data keys
@returns {Array} the formatted data
function formatData(dataset, props, expectedKeys) {
  const isArrayOrIterable = Array.isArray(dataset) || Immutable.isIterable(dataset);
  if (!isArrayOrIterable || getLength(dataset) < 1) {
    return [];
  }

  const defaultKeys = ["x", "y", "y0"];
  expectedKeys = Array.isArray(expectedKeys) ? expectedKeys : defaultKeys;

  const stringMap = {
    x: expectedKeys.indexOf("x") !== -1 ? createStringMap(props, "x") : undefined,
    y: expectedKeys.indexOf("y") !== -1 ? createStringMap(props, "y") : undefined,
    y0: expectedKeys.indexOf("y0") !== -1 ? createStringMap(props, "y") : undefined
  };

  const createAccessor = (name) => {
    return Helpers.createAccessor(props[name] !== undefined ? props[name] : name);
  };

  const accessor = expectedKeys.reduce((memo, type) => {
    memo[type] = createAccessor(type);
    return memo;
  }, {});

  const preformattedData =
    isEqual(expectedKeys, defaultKeys) &&
    props.x === "_x" &&
    props.y === "_y" &&
    props.y0 === "_y0";

  const data = preformattedData
    ? dataset
    : dataset.reduce((dataArr, datum, index) => {
        // eslint-disable-line complexity
        datum = parseDatum(datum);
        const fallbackValues = { x: index, y: datum };
        const processedValues = expectedKeys.reduce((memo, type) => {
          const processedValue = accessor[type](datum);
          const value = processedValue !== undefined ? processedValue : fallbackValues[type];
          if (value !== undefined) {
            if (typeof value === "string" && stringMap[type]) {
              memo[`${type}Name`] = value;
              memo[`_${type}`] = stringMap[type][value];
            } else {
              memo[`_${type}`] = value;
            }
          }
          return memo;
        }, {});

        const formattedDatum = assign({}, processedValues, datum);
        if (!isEmpty(formattedDatum)) {
          dataArr.push(formattedDatum);
        }

        return dataArr;
      }, []);

  const sortedData = sortData(data, props.sortKey, props.sortOrder);
  const cleanedData = cleanData(sortedData, props);
  return addEventKeys(props, cleanedData);
}