/**
   * @param config
   * @param statContent
   * @param delim
   * @param idOrdinals
   * @param stats
   * @param keyedStats
   */
  private void loadMedianStatContent(
      String statContent,
      String delim,
      int[] idOrdinals,
      Map<Integer, Double> stats,
      Map<String, Map<Integer, Double>> keyedStats) {
    String line = null;
    String[] items = null;

    Scanner scanner = new Scanner(statContent);
    while (scanner.hasNextLine()) {
      line = scanner.nextLine();
      items = line.split(delim);
      if (null != idOrdinals) {
        // with IDs
        String compId = Utility.join(items, 0, idOrdinals.length, delim);
        Map<Integer, Double> medians = keyedStats.get(compId);
        if (null == medians) {
          medians = new HashMap<Integer, Double>();
          keyedStats.put(compId, medians);
        }
        medians.put(
            Integer.parseInt(items[idOrdinals.length]),
            Double.parseDouble(items[idOrdinals.length + 1]));
      } else {
        // without IDs
        stats.put(Integer.parseInt(items[0]), Double.parseDouble(items[1]));
      }
    }
  }
 /**
  * @param config
  * @param statFilePathParam
  * @param delim
  * @param idOrdinals
  * @param stats
  * @param keyedStats
  * @throws IOException
  */
 private void loadMedianStat(
     Configuration config,
     String statFilePathParam,
     String delim,
     int[] idOrdinals,
     Map<Integer, Double> stats,
     Map<String, Map<Integer, Double>> keyedStats)
     throws IOException {
   List<String> lines = Utility.getFileLines(config, statFilePathParam);
   for (String line : lines) {
     String[] items = line.split(delim);
     if (null != idOrdinals) {
       // with IDs
       String compId = Utility.join(items, 0, idOrdinals.length, delim);
       Map<Integer, Double> medians = keyedStats.get(compId);
       if (null == medians) {
         medians = new HashMap<Integer, Double>();
         keyedStats.put(compId, medians);
       }
       medians.put(
           Integer.parseInt(items[idOrdinals.length]),
           Double.parseDouble(items[idOrdinals.length + 1]));
     } else {
       // without IDs
       stats.put(Integer.parseInt(items[0]), Double.parseDouble(items[1]));
     }
   }
 }
  /**
   * Stats for keyed data
   *
   * @param config
   * @param statsFilePath
   * @param delim
   * @param idOrdinals
   * @throws IOException
   */
  public NumericalAttrStatsManager(
      Configuration config, String statsFilePath, String delim, int[] idOrdinals)
      throws IOException {
    InputStream fs = Utility.getFileStream(config, statsFilePath);
    BufferedReader reader = new BufferedReader(new InputStreamReader(fs));
    String line = null;
    String[] items = null;

    // (0)attr ord (1)cond attr (2)sum (3)sum square (4)count (5)mean (6)variance (7)std dev (8)min
    // (9)max
    while ((line = reader.readLine()) != null) {
      items = line.split(delim);
      Tuple tuple = new Tuple();
      int i = 0;
      String compKey = Utility.join(items, 0, idOrdinals.length);
      i += idOrdinals.length;
      Integer attr = Integer.parseInt(items[i++]);
      tuple.add(Tuple.STRING, items[i++]);
      tuple.add(Tuple.DOUBLE, items[i++]);
      tuple.add(Tuple.DOUBLE, items[i++]);
      tuple.add(Tuple.INT, items[i++]);
      tuple.add(Tuple.DOUBLE, items[i++]);
      tuple.add(Tuple.DOUBLE, items[i++]);
      tuple.add(Tuple.DOUBLE, items[i++]);

      // add to map
      Map<Integer, List<Tuple>> stats = keyedStats.get(compKey);
      if (null == stats) {
        stats = new HashMap<Integer, List<Tuple>>();
        keyedStats.put(compKey, stats);
      }
      List<Tuple> statList = stats.get(attr);
      if (null == statList) {
        statList = new ArrayList<Tuple>();
        stats.put(attr, statList);
      }
      statList.add(tuple);
    }
  }