computeFeatureType = (
  name,
  data,
  uniqueDataVals = null,
  uniqCountThreshold = UNIQ_COUNT_THRESHOLD,
  uniqPercentageThreshold = UNIQ_PERCENTAGE_THRESHOLD
) => {
  // analyze type from data
  const uniques = uniqueDataVals || Array.from(new Set(data));
  const hasNaN = uniques.some(d => isNaN(d) || d === null);

  const isCategorical =
    (uniques.length < uniqCountThreshold &&
      uniques.length < data.length * uniqPercentageThreshold) ||
    hasNaN;

  // analyze type from name
  const isLatLngByName = LAT_LNG_PAIRS.reduce(
    (acc, arr) => acc.concat(arr),
    []
  ).some(suffix => name.endsWith(suffix));
  const isHexByName = HEX_INDICATORS.some(hexIndicator =>
    name.includes(hexIndicator)
  );
  return isLatLngByName || isHexByName
    ? FEATURE_TYPE.GEO
    : isCategorical
      ? FEATURE_TYPE.CATEGORICAL
      : FEATURE_TYPE.NUMERICAL;
}
@param {String} name feature name
@param {Array} data feature values
@param {Array} uniqueDataVals unique values in feature values
@return {String} one of FEATURE_TYPEs