How to create a java app that creates a very simple plot from data in a csv file

  How to create a java app that creates a very simple plot from data in a csv file



To create a java app that creates a very simple plot from data in a csv file can be done in several ways.  In this example we'll use simple readily-available technology (specifically leveraging swing, which is an older java technology) instead of using more modern options like javafx and instead of pulling in some of the really cool packages out there now that can be leveraged from maven.  Depending upon comments and interests, we may show how to do the same (or better) using those technologies.

Once you master this app, you could easily advance to more complex csv files and more complex aesthetics on the plot.  There are also a variety of plots you could explore.

This is another baby step that is worthy of practicing, by following, and then by aiming to complete more and more without referencing, and then completely by memory, and to practice often.

So let's do it, and discuss it, just a bit ...


Here's the code:

  1 import javax.swing.*;

  2 import java.awt.*;

  3 import java.awt.geom.Line2D;

  4 import java.io.BufferedReader;

  5 import java.io.FileReader;

  6 import java.io.IOException;

  7 import java.text.ParseException;

  8 import java.text.SimpleDateFormat;

  9 import java.util.ArrayList;

 10 import java.util.Date;

 11 import java.util.List;

 12 

 13 public class CsvPlotter extends JPanel {

 14 

 15     private List<Date> dates = new ArrayList<>();

 16     private List<Double> amounts = new ArrayList<>();

 17     private SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yy");

 18 

 19     public CsvPlotter(String csvFilePath) {

 20         loadCSVData(csvFilePath);

 21     }

 22 

 23     private void loadCSVData(String csvFilePath) {

 24         try (BufferedReader br = new BufferedReader(new FileReader(csvFilePath))) {

 25             String line;

 26             br.readLine(); // Skip header line

 27             while ((line = br.readLine()) != null) {

 28                 String[] values = line.split(",");

 29                 Date date = dateFormat.parse(values[0]);

 30                 double amount = Double.parseDouble(values[1]);

 31                 dates.add(date);

 32                 amounts.add(amount);

 33             }

 34         } catch (IOException | ParseException e) {

 35             e.printStackTrace();

 36         }

 37     }

 38 

 39     @Override

 40     protected void paintComponent(Graphics g) {

 41         super.paintComponent(g);

 42         Graphics2D g2 = (Graphics2D) g;

 43 

 44         double xScale = ((double) getWidth() - 2 * 50) / (dates.size() - 1);

 45         double yScale = ((double) getHeight() - 2 * 50) / getMaxAmount();

 46 

 47         List<Point> graphPoints = new ArrayList<>();

 48         for (int i = 0; i < dates.size(); i++) {

 49             int x = (int) (i * xScale + 50);

 50             int y = (int) ((getMaxAmount() - amounts.get(i)) * yScale + 50);

 51             graphPoints.add(new Point(x, y));

 52         }

 53 

 54         // Draw axes

 55         g2.drawLine(50, getHeight() - 50, 50, 50);

 56         g2.drawLine(50, getHeight() - 50, getWidth() - 50, getHeight() - 50);

 57 

 58         // Draw line graph

 59         for (int i = 0; i < graphPoints.size() - 1; i++) {

 60             int x1 = graphPoints.get(i).x;

 61             int y1 = graphPoints.get(i).y;

 62             int x2 = graphPoints.get(i + 1).x;

 63             int y2 = graphPoints.get(i + 1).y;

 64             g2.draw(new Line2D.Double(x1, y1, x2, y2));

 65         }

 66 

 67         // Draw points and labels

 68         for (int i = 0; i < graphPoints.size(); i++) {

 69             Point point = graphPoints.get(i);

 70             g2.fillOval(point.x - 4, point.y - 4, 8, 8);

 71 

 72             // Draw x and y value labels

 73             String xLabel = dateFormat.format(dates.get(i));

 74             String yLabel = String.format("%.2f", amounts.get(i));

 75 

 76             g2.drawString(xLabel, point.x - 15, getHeight() - 30); // X-axis label

 77             g2.drawString(yLabel, point.x + 5, point.y - 10);      // Y-axis label

 78         }

 79     }

 80 

 81     private double getMaxAmount() {

 82         double maxAmount = Double.MIN_VALUE;

 83         for (Double amount : amounts) {

 84             maxAmount = Math.max(maxAmount, amount);

 85         }

 86         return maxAmount;

 87     }

 88 

 89     public static void main(String[] args) {

 90         JFrame frame = new JFrame("CSV Data Plot");

 91         CsvPlotter plotter = new CsvPlotter(args[0]);

 92         frame.getContentPane().add(plotter);

 93         frame.setSize(800, 600);

 94         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 95         frame.setVisible(true);

 96     }

 97 }

 98 


Here's what we used when building this code:

  • java 8
  • vim editor (note: we have much love for intellij and other editors too!)
  • code was placed in a file named CsvPlotter.java

You need to create the csv file that you want to use, but I've included an example below.

The contents of a sample csv file finances_zoom.csv file:

date,amount,notes

8/12/24,31.98,

7/12/24,31.98,

6/12/24,31.98,

5/13/24,31.98,

4/12/24,31.98,

3/12/24,31.98,

2/12/24,31.98,

1/12/24,31.98,

12/12/23,31.98,

11/13/23,31.98,

10/12/23,31.98,

9/12/23,31.98,

8/22/23,10.83,

8/14/23,15.99,

7/12/23,15.99,

6/12/23,15.99,

Here's what we did to compile and run the code:

  • javac CsvPlotter.java

  • java CsvPlotter finances_zoom.csv

Here's what you'll see when you run it:

Here's a bit of description about the code and concepts used:

  • the public class name of CsvPlotter is the same as the filename, and that's important in order for the file class to compile
  • The typical public static void main function is added and is the entry point to the application
  • We need to import additional capabilities to have what we need for this program.
    • Multiple of the imports leverage the capabilities of swing (the user interface aspect of our app)
    • The BufferedReader, FileReader, and Exceptions help us with the reading of our input csv file.
    • The SimpleDateFormat helps us with standard reading of dates to support additional capability if we wanted to use (sorting, filtering, etc).  The Date import helps here also.
    • The ArrayList and List imports help us to use very popular data structures to parse, store, access and manipulate the data we read from the csv files.
  • The JPanel class is extended so that we can leverage its built-in capabilities and enhance them, making it easy for us to provide a simple display.  That's generally the pattern for leveraging swing.
  • The loadCSVData function does as it's named, it accepts an input parameter of the csv filename and then it opens up the file and reads each one of its lines and stores its data line by line.  It specifically expects commas to separate the data on each row.  It also handles any exceptions.
  • The paintComponent function is from JPanel and we override what happens when this function is called by providing our code for it and leveraging the Override annotation.  The details of the axis and each point being placed on the right position of the plot is handled here.
  • The getMaxAmount function is simple and helps make sure our y axis is large enough (tall enough).
  • The public static void main function leverages an expected command line argument (holding the csv file name) and then creates an instance of the CsvPlotter class, sets the size (which you could easily adjust), and allows it to show up on the screen as well as setting it up for a graceful exit if you click on the x to close it.

Another baby step completed, nice job!

Want to know how to do something in java or have any questions?  Let me know by commenting, and we'll consider getting there as we continue to take baby steps!

Copyright © 2024 correlateencourage - All Rights Reserved.

..............................

Practicing baby steps is one of the things we believe correlates with success, and keeping track of your practice experience is another.  It's one of the many things you can track with our correlateencourage app, available here at the apple store: https://apps.apple.com/us/app/correlateencourage/id6504427387  

Comments

Popular posts from this blog

How to create a java app that converts fahrenheit to celsius and allows you to list the cities you want converted in an input text file

Learn Java: The ABC's of Java