Java Arena
Step 8 of 8

Charts from your own data

This step puts the module together: a file of rows, some computing, and a chart that shows the result honestly. The last challenge is a small tool that charts any data written in its format.

From a file to a chart, the whole way

A household writes down its electricity meter's reading at the start of each month. The meter only counts up, so the electricity used in a month is the difference between two readings in a row:

The file meter.csv
month,kWh
Jan,10250
Feb,10560
Mar,10830
Apr,11040
May,11190

The computing goes in a class of its own, and the window charts what it returns:

Main.java
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        List<String> months = new ArrayList<>();
        List<Integer> readings = new ArrayList<>();
        List<String> lines = Files.readAllLines(Paths.get("meter.csv"));
        for (int i = 1; i < lines.size(); i++) {
            String[] parts = lines.get(i).split(",");
            months.add(parts[0]);
            readings.add(Integer.valueOf(parts[1]));
        }
        List<Integer> used = Meter.differences(readings);
        System.out.println(used);

        CategoryAxis monthAxis = new CategoryAxis();
        monthAxis.setLabel("Month");
        NumberAxis kwhAxis = new NumberAxis();
        kwhAxis.setLabel("Electricity used (kWh)");
        BarChart<String, Number> chart = new BarChart<>(monthAxis, kwhAxis);
        chart.setTitle("Electricity used per month");
        chart.setLegendVisible(false);
        XYChart.Series<String, Number> series = new XYChart.Series<>();
        series.setName("kWh");
        for (int i = 0; i < used.size(); i++) {
            series.getData().add(new XYChart.Data<>(months.get(i), used.get(i)));
        }
        chart.getData().add(series);

        stage.setScene(new Scene(chart));
        stage.setTitle("Electricity");
        stage.show();
    }

    public static void main(String[] args) {
        launch(Main.class);
    }
}
Meter.java
import java.util.ArrayList;
import java.util.List;

public class Meter {

    public static List<Integer> differences(List<Integer> readings) {
        List<Integer> used = new ArrayList<>();
        for (int i = 1; i < readings.size(); i++) {
            used.add(readings.get(i) - readings.get(i - 1));
        }
        return used;
    }
}
The window

This window is wider than the screen: scroll it sideways, or read it as text below.

The window as text
Window "Electricity"
  BarChart "Electricity used per month" (no legend)
    x axis CategoryAxis "Month"
    y axis NumberAxis "Electricity used (kWh)"
    series "kWh": ("Jan", 310) ("Feb", 270) ("Mar", 210) ("Apr", 150)
Output
[310, 270, 210, 150]

Five readings give four differences: the reading of February minus that of January is what January used, so the bars are January to April. months.get(i) pairs difference i with the month it was used in.

Here are the choices that every chart of this module made, as a list to go through for a chart of your own:

  1. Read the rows: skip the header, split on the separator, turn the text into numbers with Integer.valueOf or Double.valueOf, and decide what a missing value (-) means: left out, or 0 because nothing happened.
  2. Compute what the chart shows (totals, differences, a formula) in a plain class, and print it to check it before any chart exists.
  3. Choose the chart: a line chart when x is a number and the values change along it, a bar chart to compare categories, a scatter chart for points that have no order.
  4. Axes: labels with units, bars from 0, fixed bounds when a slider changes the data, and the same scale for charts that are compared.
  5. Series: a name for each, the legend when there are several, the points from the smallest x up, and series in an order you chose (the file's, or sorted names), never a HashMap's.

The end of section 14.1

This module followed the MOOC's section 14.1, on data visualization. You read rows of data into numbers, lists and maps, drew line charts with NumberAxis, XYChart.Series and XYChart.Data, made several series from a file's columns or from a map, computed series from a formula in a plain class, redrew a chart with a Slider and its valueProperty() listener, compared categories with a BarChart and a CategoryAxis, and kept charts honest. Module 52 follows the MOOC's section 14.2: it draws on a canvas with colors and the mouse, works with images pixel by pixel, and explains sound.

Your task

Challenge 1 of 3

A sensor outside a mountain hut reads the temperature three times a day, in whole degrees, and writes temps.csv. A failed reading has a - (careful: -3 is a reading, 3 degrees below zero):

day,hour,temp
1,6,4
1,12,11
1,18,8
2,6,-3
2,12,-
2,18,6
3,6,5
3,12,14
3,18,10

Write start so that the window, titled Mountain hut, shows a line chart (the scene's root) with the title Coldest and warmest, an auto-ranging x axis labeled Day, an auto-ranging y axis labeled Temperature (°C) and a visible legend. It has two series, first Lowest, then Highest: for each day with at least one reading, Lowest has the point (day, the day's lowest reading) and Highest the point (day, the day's highest reading), from the smallest day up. The rows may come in any order. The task card shows the window for the file above.

Challenge 2

A program sums up a week of litter picking by day: the bags filled by each volunteer group. What does it print?

Challenge 3

A chart tool for your own data: it reads chart.csv, whose first line says the kind of chart and its title, separated by a comma (bar,Books read or line,Books read). The second line is the header, which names the x values and the y values, and the rows follow. A - is a missing value:

bar,Books read in the club
month,books
Jan,3
Feb,5
Mar,-
Apr,4

Write start. The window, titled My chart, shows the chart (the scene's root) with the title from the first line, no legend and one series, named as the header's second value, with a point (x, y) for each row whose y isn't -, in the order of the file. Read the y values as doubles.

  • For bar, it's a bar chart with a category axis labeled as the header's first value (here month) and an auto-ranging number axis labeled as the header's second value (here books).
  • For line, it's a line chart with two auto-ranging number axes labeled the same way, and the x values are numbers too (read them as doubles).

The task card shows the window for the file above. The tool charts any file in this form, so on your own computer, with JavaFX installed (module 48 says where to find how), you can give it data of your own.