add jenks nature breaks module

This commit is contained in:
wyq 2023-01-10 22:07:55 +08:00
parent 7a3e2e606c
commit 87f4309869
12 changed files with 630 additions and 39 deletions

View File

@ -21,7 +21,7 @@ public class Popup extends JWindow {
private final static int MAX_HEIGHT = 300;
private final static int MIN_WIDTH = 200;
private final static int MAX_WIDTH = 400;
private final JTextComponent textCompnent;
private final JTextComponent textComponent;
private int dotPosition;
private final JList list;
private String[] originalData;
@ -36,7 +36,7 @@ public class Popup extends JWindow {
*/
public Popup(JFrame frame, JTextComponent textComponent){
super(frame);
this.textCompnent = textComponent;
this.textComponent = textComponent;
this.setSize(200, 200);
this.list = new JList();
this.list.addKeyListener(new KeyAdapter(){
@ -86,7 +86,7 @@ public class Popup extends JWindow {
// @Override
// public void show(){
// this.dotPosition = this.textCompnent.getCaretPosition();
// this.dotPosition = this.textComponent.getCaretPosition();
// this.setSize(this.getPreferredSize());
// //super.show();
// this.setVisible(true);
@ -97,12 +97,12 @@ public class Popup extends JWindow {
this.setLocation(displayPoint);
this.setBounds(displayPoint.x, displayPoint.y, size.width, size.height);
this.setMethods(list);
if (this.textCompnent != null)
this.dotPosition = this.textCompnent.getCaretPosition();
if (this.textComponent != null)
this.dotPosition = this.textComponent.getCaretPosition();
//this.show();
this.setVisible(true);
this.list.setSelectedIndex(0);
this.setAlwaysOnTop(true);
//this.setAlwaysOnTop(true);
}
/**
@ -113,11 +113,11 @@ public class Popup extends JWindow {
Dimension size = this.getPreferredSize();
this.setLocation(displayPoint);
this.setBounds(displayPoint.x, displayPoint.y, size.width, size.height);
if (this.textCompnent != null)
this.dotPosition = this.textCompnent.getCaretPosition();
if (this.textComponent != null)
this.dotPosition = this.textComponent.getCaretPosition();
this.setVisible(true);
this.list.setSelectedIndex(0);
this.setAlwaysOnTop(true);
//this.setAlwaysOnTop(true);
}
@Override
@ -201,12 +201,12 @@ public class Popup extends JWindow {
Object value = this.list.getSelectedValue();
if (value != null){
int startPosition = this.dotPosition;
int caretPosition = this.textCompnent.getCaretPosition();
this.textCompnent.select(startPosition, caretPosition) ;
this.textCompnent.replaceSelection(value.toString());
int caretPosition = this.textComponent.getCaretPosition();
this.textComponent.select(startPosition, caretPosition) ;
this.textComponent.replaceSelection(value.toString());
caretPosition = startPosition + value.toString().length();
try {
this.textCompnent.setCaretPosition(caretPosition);
this.textComponent.setCaretPosition(caretPosition);
} catch (Exception e){
}

View File

@ -31,7 +31,7 @@ public class Tip extends JWindow {
this.textarea.setEditable(false);
JScrollPane jscrollpane = new JScrollPane(this.textarea);
this.getContentPane().add(jscrollpane);
this.setAlwaysOnTop(true);
//this.setAlwaysOnTop(true);
}
// </editor-fold>
// <editor-fold desc="Get Set Methods">

View File

@ -46,6 +46,7 @@ import org.fife.ui.rtextarea.RTextScrollPane;
private MITextEditorPane _textArea;
private String _title;
private File _file = null;
private Font font;
private JTabbedPane _parent;
// </editor-fold>
// <editor-fold desc="Constructor">
@ -244,6 +245,26 @@ import org.fife.ui.rtextarea.RTextScrollPane;
* @param font The font to use.
*/
public void setTextFont(Font font) {
if (font != null) {
this.font = font;
SyntaxScheme ss = _textArea.getSyntaxScheme();
ss = (SyntaxScheme) ss.clone();
for (int i = 0; i < ss.getStyleCount(); i++) {
if (ss.getStyle(i) != null) {
ss.getStyle(i).font = font;
}
}
_textArea.setSyntaxScheme(ss);
_textArea.setFont(font);
}
}
/**
* Set the font for all token types.
*
* @param font The font to use.
*/
public void updateTextFont() {
if (font != null) {
SyntaxScheme ss = _textArea.getSyntaxScheme();
ss = (SyntaxScheme) ss.clone();

View File

@ -1,11 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui">
<RecentFolder Folder="D:\Run\emips"/>
<RecentFolder Folder="D:\Run\emips\run_meic"/>
<RecentFolder Folder="D:\Run\emips\test"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\common_math\stats">
<RecentFolder Folder="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\grads"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\annotate"/>
@ -15,33 +11,32 @@
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\boxplot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\funny"/>
<RecentFolder Folder="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\toolbox"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\toolbox\emips"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\stats"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\main_gui.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\_reload.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\emission_panel.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\vertical_panel.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\temporal_panel.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\chemical_panel.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\spatial_panel.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\run_panel.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\common_math\stats\jenks_breaks.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\common_math\stats\jenks_breaks_2.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\main_gui.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\_reload.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\emission_panel.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\vertical_panel.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\temporal_panel.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\chemical_panel.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\spatial_panel.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\EMIPS\emips\gui\run_panel.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\common_math\stats\jenks_breaks.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\common_math\stats\jenks_breaks_2.py"/>
</RecentFiles>
</File>
<Font>
<TextFont FontName="YaHei Consolas Hybrid" FontSize="14"/>
</Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatLightLaf"/>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
</MeteoInfo>

View File

@ -2,8 +2,10 @@ from .stats import *
from .distributions import *
from ._multivariate import *
from .kde import GaussianKDE
from ._jenks import *
__all__ = []
__all__ += stats.__all__
__all__ += distributions.__all__
__all__ += _multivariate.__all__
__all__ += _multivariate.__all__
__all__ += _jenks.__all__

View File

@ -0,0 +1,133 @@
from org.meteoinfo.math.stats import StatsUtil, Jenks
from ..core import numeric as np
__all__ = ["jenks_breaks", "JenksNaturalBreaks"]
class JenksNaturalBreaks(object):
"""
A class that can be used to classify a sequence of numbers into groups (clusters) using Fisher-Jenks natural breaks.
"""
def __init__(self, n_classes=6):
"""
Parameters
----------
n_classes : int
The number of classes to be generated by the classifier.
"""
self.n_classes = n_classes
def __repr__(self):
return "JenksNaturalBreaks(n_classes={})".format(self.n_classes)
def __str__(self):
return self.__repr__()
def fit(self, x):
"""
Parameters
----------
x : array-like
The sequence of numbers (integer/float) to be classified.
"""
x = np.asarray(x)
self._jenks = Jenks()
self._jenks.addValues(x.asarray())
self._breaks = self._jenks.computeBreaks(self.n_classes)
self.breaks_ = np.array(self._breaks.getClassValues())
self.inner_breaks_ = self.breaks_[1:-1] # because inner_breaks is more
self.labels_ = self.predict(x)
self.groups_ = self.group(x)
def predict(self, x):
"""
Predicts the class of each element in x.
Parameters
----------
x : scalar or array-like
Returns
-------
array
"""
x = np.asarray(x)
r = self._breaks.classOf(x.asarray())
return np.array(r)
def group(self, x):
"""
Groups the elements in x into groups according to the classifier.
Parameters
----------
x : array-like
The sequence of numbers (integer/float) to be classified.
Returns
-------
list of numpy.array
The list of groups that contains the values of x.
"""
arr = np.array(x)
groups_ = [arr[arr <= self.inner_breaks_[0]]]
for idx in range(len(self.inner_breaks_))[:-1]:
groups_.append(arr[(arr > self.inner_breaks_[idx]) & (arr <= self.inner_breaks_[idx + 1])])
groups_.append(arr[arr > self.inner_breaks_[-1]])
return groups_
def goodness_of_variance_fit(self, x):
"""
Parameters
----------
x : array-like
Returns
-------
float
The goodness of variance fit.
"""
gvf = self._breaks.gvf()
return gvf
def get_label_(self, val):
"""
Compute the group label of the given value.
Parameters
----------
val : float
The value to be classified.
Returns
-------
int : The label of the value.
"""
return self._breaks.classOf(val)
def jenks_breaks(a, n_classes, gvf=False):
"""
Compute natural breaks (Fisher-Jenks algorithm) on a sequence of `values`,
given `n_classes`, the number of desired class.
:param a: (*array*) Input data array.
:param n_classes: (*int*) The number of desired class.
:param gvf: (*float*) Whether return gvf (Goodness of Variance Fit) value. Default is `False`.
:return: (*array*) The computed break values, including minimum and maximum, in order
to have all the bounds for building `n_classes` classes,
so the returned list has a length of `n_classes` + 1.
"""
if isinstance(a, (list, tuple)):
a = np.array(a)
if gvf:
r = StatsUtil.jenksBreaksGvf(a._array, n_classes)
return np.array(r[0]), r[1]
else:
r = StatsUtil.jenksBreaks(a._array, n_classes)
return np.array(r)

View File

@ -2,6 +2,7 @@ from ..core import numeric as np
import stats
from ..linalg import linalg
class GaussianKDE(object):
"""
Representation of a kernel-density estimate using Gaussian kernels.

View File

@ -336,8 +336,10 @@ public class FrmSetting extends javax.swing.JDialog {
Theme theme = Theme.load(getClass().getResourceAsStream(
"/org/fife/ui/rsyntaxtextarea/themes/" + themeName + ".xml"));
this.parent.getEditorDock().setTheme(theme);
for (TextEditor textEditor : this.parent.getEditorDock().getAllTextEditor())
theme.apply(textEditor.getTextArea());
for (TextEditor textEditor : this.parent.getEditorDock().getAllTextEditor()) {
theme.apply(textEditor.getTextArea());
textEditor.updateTextFont();
}
} catch (IOException ioe) { // Never happens
ioe.printStackTrace();
}

View File

@ -0,0 +1,404 @@
package org.meteoinfo.math.stats;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.google.common.collect.Lists;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.DataType;
import org.meteoinfo.ndarray.IndexIterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* The Jenks optimization method, also called the Jenks natural breaks
* classification method, is a data classification method designed to determine
* the best arrangement of values into different classes. This is done by
* seeking to minimize each classs average deviation from the class mean, while
* maximizing each classs deviation from the means of the other groups. In
* other words, the method seeks to reduce the variance within classes and
* maximize the variance between classes.
*/
public class Jenks {
private LinkedList<Double> list = Lists.newLinkedList();
public void addValue(double value) {
list.add(value);
}
public void addValues(double... values) {
for (double value : values) {
addValue(value);
}
}
/**
* Add values
* @param values Values array
*/
public void addValues(Array values) {
IndexIterator vIter = values.getIndexIterator();
while (vIter.hasNext()) {
addValue(vIter.getDoubleNext());
}
}
/**
* @return
*/
public Breaks computeBreaks() {
double[] list = toSortedArray();
int uniqueValues = countUnique(list);
if (uniqueValues <= 3) {
return computeBreaks(list, uniqueValues);
}
Breaks lastBreaks = computeBreaks(list, 2);
double lastGvf = lastBreaks.gvf();
double lastImprovement = lastGvf - computeBreaks(list, 1).gvf();
for (int i = 3; i <= Math.min(6, uniqueValues); ++i) {
Breaks breaks = computeBreaks(list, 2);
double gvf = breaks.gvf();
double marginalImprovement = gvf - lastGvf;
if (marginalImprovement < lastImprovement) {
return lastBreaks;
}
lastBreaks = breaks;
lastGvf = gvf;
lastImprovement = marginalImprovement;
}
return lastBreaks;
}
private double[] toSortedArray() {
double[] values = new double[this.list.size()];
for (int i = 0; i != values.length; ++i) {
values[i] = this.list.get(i);
}
Arrays.sort(values);
return values;
}
private int countUnique(double[] sortedList) {
int count = 1;
for (int i = 1; i < sortedList.length; ++i) {
if (sortedList[i] != sortedList[i - 1]) {
count++;
}
}
return count;
}
/**
* @param list sorted list of values
* @param numclass int number of classes
* @return int[] breaks (upper indices of class)
*/
public Breaks computeBreaks(int numclass) {
return computeBreaks(toSortedArray(), numclass, new Identity());
}
private Breaks computeBreaks(double[] list, int numclass) {
return computeBreaks(list, numclass, new Identity());
}
private Breaks computeBreaks(double[] list, int numclass, DoubleFunction transform) {
int numdata = list.length;
if (numdata == 0) {
return new Breaks(new double[0], new int[0]);
}
double[][] mat1 = new double[numdata + 1][numclass + 1];
double[][] mat2 = new double[numdata + 1][numclass + 1];
for (int i = 1; i <= numclass; i++) {
mat1[1][i] = 1;
mat2[1][i] = 0;
for (int j = 2; j <= numdata; j++) {
mat2[j][i] = Double.MAX_VALUE;
}
}
double v = 0;
for (int l = 2; l <= numdata; l++) {
double s1 = 0;
double s2 = 0;
double w = 0;
for (int m = 1; m <= l; m++) {
int i3 = l - m + 1;
double val = transform.apply(list[i3 - 1]);
s2 += val * val;
s1 += val;
w++;
v = s2 - (s1 * s1) / w;
int i4 = i3 - 1;
if (i4 != 0) {
for (int j = 2; j <= numclass; j++) {
if (mat2[l][j] >= (v + mat2[i4][j - 1])) {
mat1[l][j] = i3;
mat2[l][j] = v + mat2[i4][j - 1];
}
}
}
}
mat1[l][1] = 1;
mat2[l][1] = v;
}
int k = numdata;
int[] kclass = new int[numclass];
kclass[numclass - 1] = list.length - 1;
for (int j = numclass; j >= 2; j--) {
int id = (int) (mat1[k][j]) - 2;
kclass[j - 2] = id;
k = (int) mat1[k][j] - 1;
}
return new Breaks(list, kclass);
}
private interface DoubleFunction {
double apply(double x);
}
private static class Log10 implements DoubleFunction {
@Override
public double apply(double x) {
return Math.log10(x);
}
}
public static class Identity implements DoubleFunction {
@Override
public double apply(double x) {
return x;
}
}
public static class Breaks {
private double[] sortedValues;
private int[] breaks;
/**
* @param sortedValues the complete array of sorted data values
* @param breaks the indexes of the values within the sorted array that begin new classes
*/
private Breaks(double[] sortedValues, int[] breaks) {
this.sortedValues = sortedValues;
this.breaks = breaks;
}
/**
* The Goodness of Variance Fit (GVF) is found by taking the difference
* between the squared deviations from the array mean (SDAM) and the
* squared deviations from the class means (SDCM), and dividing by the
* SDAM
*
* @return
*/
public double gvf() {
double sdam = sumOfSquareDeviations(sortedValues);
double sdcm = 0.0;
for (int i = 0; i != numClasses(); ++i) {
sdcm += sumOfSquareDeviations(classList(i));
}
return (sdam - sdcm) / sdam;
}
private double sumOfSquareDeviations(double[] values) {
double mean = mean(values);
double sum = 0.0;
for (int i = 0; i != values.length; ++i) {
double sqDev = Math.pow(values[i] - mean, 2);
sum += sqDev;
}
return sum;
}
public double[] getValues() {
return sortedValues;
}
private double[] classList(int i) {
int classStart = (i == 0) ? 0 : breaks[i - 1] + 1;
int classEnd = breaks[i];
double list[] = new double[classEnd - classStart + 1];
for (int j = classStart; j <= classEnd; ++j) {
list[j - classStart] = sortedValues[j];
}
return list;
}
/**
* Get value arrays for each group
* @return Value arrays for each group
*/
public List<Array> getGroups() {
List<Array> groups = new ArrayList<>();
int n = numClasses();
for (int i = 0; i < n; i++) {
double[] values = classList(i);
groups.add(Array.factory(DataType.DOUBLE, new int[]{values.length}, values));
}
return groups;
}
/**
* @param classIndex
* @return the minimum value (inclusive) of the given class
*/
public double getClassMin(int classIndex) {
if (classIndex == 0) {
return sortedValues[0];
} else {
return sortedValues[breaks[classIndex - 1] + 1];
}
}
/**
* @param classIndex
* @return the maximum value (inclusive) of the given class
*/
public double getClassMax(int classIndex) {
return sortedValues[breaks[classIndex]];
}
public int getClassCount(int classIndex) {
if (classIndex == 0) {
return breaks[0] + 1;
} else {
return breaks[classIndex] - breaks[classIndex - 1];
}
}
private double mean(double[] values) {
double sum = 0;
for (int i = 0; i != values.length; ++i) {
sum += values[i];
}
return sum / values.length;
}
public int numClasses() {
return breaks.length;
}
/**
* Get classes bound values
* @return Classes bound values
*/
public Array getClassValues() {
double[] classValues = new double[breaks.length + 1];
classValues[0] = sortedValues[0];
for (int i = 0; i < breaks.length; i++) {
classValues[i + 1] = getClassMax(i);
}
return Array.factory(DataType.DOUBLE, new int[]{classValues.length}, classValues);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i != numClasses(); ++i) {
if (getClassMin(i) == getClassMax(i)) {
sb.append(getClassMin(i));
} else {
sb.append(getClassMin(i)).append(" - ").append(getClassMax(i));
}
sb.append(" (" + getClassCount(i) + ")");
sb.append(" = ").append(Arrays.toString(classList(i)));
sb.append("\n");
}
return sb.toString();
}
public String printClusters() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i != numClasses(); ++i) {
if (getClassMin(i) == getClassMax(i)) {
sb.append(getClassMin(i));
} else {
sb.append(getClassMin(i)).append(" - ").append(getClassMax(i));
}
sb.append(" (" + getClassCount(i) + ");");
// sb.append("\n");
}
return sb.toString();
}
public int classOf(double value) {
for (int i = 0; i != numClasses(); ++i) {
if (value <= getClassMax(i)) {
return i;
}
}
return numClasses() - 1;
}
/**
* Get class index of values
* @param values The values array
* @return Class index array
*/
public Array classOf(Array values) {
Array r = Array.factory(DataType.INT, values.getShape());
IndexIterator vIter = values.getIndexIterator();
IndexIterator rIter = r.getIndexIterator();
while (vIter.hasNext()) {
rIter.setIntNext(classOf(vIter.getDoubleNext()));
}
return r;
}
public static void main(String[] args) {
Jenks jenks = new Jenks();
jenks.addValue(1.0);
jenks.addValue(2.0);
jenks.addValue(2.0);
jenks.addValue(2.0);
jenks.addValue(3.0);
}
}
}

View File

@ -16,14 +16,9 @@ import org.apache.commons.math4.legacy.stat.correlation.PearsonsCorrelation;
import org.apache.commons.math4.legacy.stat.correlation.SpearmansCorrelation;
import org.apache.commons.math4.legacy.stat.inference.InferenceTestUtils;
import org.apache.commons.math4.legacy.stat.regression.OLSMultipleLinearRegression;
import org.meteoinfo.ndarray.*;
import org.meteoinfo.ndarray.math.ArrayMath;
import org.meteoinfo.ndarray.math.ArrayUtil;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.DataType;
import org.meteoinfo.ndarray.Index;
import org.meteoinfo.ndarray.InvalidRangeException;
import org.meteoinfo.ndarray.MAMath;
import org.meteoinfo.ndarray.Range;
import smile.math.special.Erf;
/**
@ -528,4 +523,42 @@ public class StatsUtil {
return new double[]{s, p};
}
/**
* Calculate Jenks breaks
* @param a The input data array
* @param nClass Number of classes
* @return Jenks breaks value array
*/
public static Array jenksBreaks(Array a, int nClass) {
Jenks jenks = new Jenks();
IndexIterator iterA = a.getIndexIterator();
while (iterA.hasNext()) {
jenks.addValue(iterA.getDoubleNext());
}
Jenks.Breaks breaks = jenks.computeBreaks(nClass);
Array r = breaks.getClassValues();
return r;
}
/**
* Calculate Jenks breaks
* @param a The input data array
* @param nClass Number of classes
* @return Jenks breaks value array and gvf value
*/
public static Object[] jenksBreaksGvf(Array a, int nClass) {
Jenks jenks = new Jenks();
IndexIterator iterA = a.getIndexIterator();
while (iterA.hasNext()) {
jenks.addValue(iterA.getDoubleNext());
}
Jenks.Breaks breaks = jenks.computeBreaks(nClass);
Array r = breaks.getClassValues();
return new Object[]{r, breaks.gvf()};
}
}