Contents

Apache Commons Math3库的Frequency类简介

1.概述

在本教程中,我们将了解如何借助 Apache Commons Frequency 类在直方图上呈现数据。

Frequency 类是本文 探讨的 Apache Commons Math 库的一部分。

直方图是连接条形图,显示数据集中一系列数据的出现。它与条形图的不同之处在于它用于显示连续的定量变量的分布,而条形图用于显示分类数据。

2. 项目依赖

在本文中,我们将使用具有以下依赖项的 Maven 项目:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-math3</artifactId>
    <version>3.6.1</version>
</dependency>
<dependency>
    <groupId>org.knowm.xchart</groupId>
    <artifactId>xchart</artifactId>
    <version>3.5.2</version>
</dependency>

commons-math3库包含 我们将用来确定数据集中变量出现的 Frequency 类。我们将使用 xchart 库在 GUI 中显示直方图。

最新版本的commons-math3xchart  可以在 Maven Central 上找到。

3. 计算变量的频率

在本教程中,我们将使用包含特定学校学生年龄的数据集。我们希望看到不同年龄组的频率并在直方图上观察它们的分布。

让我们用 List集合来表示数据集,并使用它来填充 Frequency类的实例:

List<Integer> datasetList = Arrays.asList(
  36, 25, 38, 46, 55, 68, 
  72, 55, 36, 38, 67, 45, 22, 
  48, 91, 46, 52, 61, 58, 55);
Frequency frequency = new Frequency();
datasetList.forEach(d -> frequency.addValue(Double.parseDouble(d.toString())));

现在我们已经填充了 Frequency类的实例,我们将获取 bin 中每个年龄的计数并将其相加,以便我们可以获得特定年龄组中年龄的总频率

datasetList.stream()
  .map(d -> Double.parseDouble(d.toString()))
  .distinct()
  .forEach(observation -> {
      long observationFrequency = frequency.getCount(observation);
      int upperBoundary = (observation > classWidth)
        ? Math.multiplyExact( (int) Math.ceil(observation / classWidth), classWidth)
        : classWidth;
      int lowerBoundary = (upperBoundary > classWidth)
        ? Math.subtractExact(upperBoundary, classWidth)
        : 0;
      String bin = lowerBoundary + "-" + upperBoundary;
      updateDistributionMap(lowerBoundary, bin, observationFrequency);
  });

从上面的代码片段中,我们首先使用 Frequency类的getCount()确定observation的频率。该方法返回observation的发生总数

使用当前observation,我们通过计算其相对于类宽度的上下边界(即 10 )来动态确定它所属的组。

上下边界连接起来形成一个 bin, 使用updateDistributionMap()将其与observation频率一起存储在distributionMap中。

如果 bin已经存在,我们更新频率,否则我们将其添加为键并将当前observation的频率设置为其值。请注意,我们会跟踪处理后的观察结果以避免重复。

Frequency类还具有确定数据集中变量的百分比和累积百分比的方法。

4. 绘制直方图

现在我们已经将原始数据集处理为年龄组及其各自频率的地图,我们可以使用 xchart库在直方图中显示数据:

CategoryChart chart = new CategoryChartBuilder().width(800).height(600)
  .title("Age Distribution")
  .xAxisTitle("Age Group")
  .yAxisTitle("Frequency")
  .build();
chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);
chart.getStyler().setAvailableSpaceFill(0.99);
chart.getStyler().setOverlapped(true);
List yData = new ArrayList();
yData.addAll(distributionMap.values());
List xData = Arrays.asList(distributionMap.keySet().toArray());
chart.addSeries("age group", xData, yData);
new SwingWrapper<>(chart).displayChart();

我们使用图表构建器创建了一个 CategoryChart实例,然后我们对其进行配置并使用 x 和 y 轴的数据填充它。

最后,我们使用SwingWrapper在 GUI 中显示图表 :

/uploads/apache_commons_frequency/1.png

从上面的直方图可以看出,80-90 岁的学生没有,而 50-60 岁的学生占主导地位。这很可能是博士生或博士后。

我们也可以说直方图具有正态分布。