DEV Community

Cover image for Izuku - 2D Data Visualization and Manipulation in NodeJS
Conrad Reeves
Conrad Reeves

Posted on

Izuku - 2D Data Visualization and Manipulation in NodeJS

Izuku is a simple, fast, and powerful tabular data representation and manipulation library written in TypeScript. It is designed to be used to view, manipulate and debug 2D data in NodeJS applications.

The core of Izuku is the Frame class that represents a 2D array of data. It is designed to be used as a data structure for tabular data. Izuku is heavily inspired by Pandas.

Note: Izuku is not a replacement for Pandas and should not be used for data analysis. It is designed to be used for data visualization and debugging. It can, however, handle large datasets and help you understand your data better but comes at some cost in performance. Since, Pandas is based on NumPy, and NumPy is written in C, Pandas would be much faster than Izuku.

Installation

Izuku is available on npm. To install Izuku, run the following command:

npm install izuku
Enter fullscreen mode Exit fullscreen mode

Showing Data

As defined above, the basic usage of Izuku is to create a Frame object and manipulate it. You can use either an 2D array, a JSON object or file, or a CSV File to create a Frame. The following example creates a Frame from a 2D array:

import { Frame } from 'izuku';
// alternatively, const { Frame } = require('izuku');

// define some column names as an array
const header = ['Name', 'Age', 'Gender', 'Country'];

// define some data as a 2D array
const data = [
  ['Arthur', 21, 'Male', 'USA'],
  ['Betty', 20, 'Female', 'Canada'],
  ['Victor', 25, 'Male'],
  ['Dodger', 30, 'Male', 'Canada'],
  ['Rayan', 21, 'Male', 'Russia'],
  ['Skitley', 29, 'Female', 'Germany'],
  ['Victoria', 89, 'Female', 'UK'],
  ['Tiger', 23, 'Male', 'India'],
  ['Killjoy', null, 'Female', 'Riot']
];

// create a frame, header is optional
const frame = new Frame(data, header);

// print the frame
frame.show();
Enter fullscreen mode Exit fullscreen mode

The above code creates a frame and prints it to the console. It looks like this:

┌───────┬──────────┬─────┬────────┬─────────┐
│ Index │ Name     │ Age │ Gender │ Country │
├───────┼──────────┼─────┼────────┼─────────┤
│ 0     │ Arthur   │ 21  │ Male   │ USA     │
│ 1     │ Betty    │ 20  │ Female │ Canada  │
│ 2     │ Victor   │ 25  │ Male   │         │
│ ...   │ ...      │ ... │ ...    │ ...     │
│ 6     │ Victoria │ 89  │ Female │ UK      │
│ 7     │ Tiger    │ 23  │ Male   │ India   │
│ 8     │ Killjoy  │     │ Female │ Riot    │
└───────┴──────────┴─────┴────────┴─────────┘
Enter fullscreen mode Exit fullscreen mode

Loading from JSON or CSV file

You can also load frames from JSON or CSV files. Here's how:

// if you have a JSON file, import it or you can use JSON object
import JSONData from './users.json';

const frame = new Frame().fromJSON(JSONData)
Enter fullscreen mode Exit fullscreen mode
// import path for loading CSV file
import path = require('path');

// define the CSV file path
const csvPath = path.join(__dirname, 'users.csv');

const frame = new Frame().fromCSV(csvPath)
Enter fullscreen mode Exit fullscreen mode

Frame Properties

There are some properties attached to the frame class. You can tap into those properties by using the dot (.) notation.

Note: Frame methods are not available on the properties. You need to console.log(propertyName) to see the property values.

rowdata

The rowdata property is an array of arrays that represents the data in the frame.

Note: The rowdata property is read-only. If you want to modify the data in the frame, you can use the data() method.

const rowdata = frame.rowdata;
console.log(rowdata); // prints "data" array
Enter fullscreen mode Exit fullscreen mode

columns

The columns property is an array of strings that represents the column names in the frame.

Note: The columns property is read-only. If you want to modify the column names in the frame, you can use the header() method.

const columns = frame.columns;
console.log(columns); // prints "header" array
Enter fullscreen mode Exit fullscreen mode

size

The size property gives the number of elements present in the frame.

Note: The size property is read-only and is automatically generated when the frame is created. Size can change if data is modified.

const size = frame.size;
console.log(size); // prints size. ex: 9
Enter fullscreen mode Exit fullscreen mode

shape

The shape property gives the number of rows and columns present in the frame.

Note: The shape property is read-only and is automatically generated when the frame is created. Shape can change if data is modified.

const shape = frame.shape;
console.log(shape); // prints shape. ex: 9 x 4
Enter fullscreen mode Exit fullscreen mode

Frame Methods

There are some methods attached to the frame class. You can tap into those methods by using the dot (.) notation. Most of the methods are chainable.

data()

The data() method is used to modify the data in the frame. It takes the same data argument as the constructor – which is an array of arrays.

Note: If you use data method without passing any argument, it will simply return the frame.

const data = [[...], [...], ...];
const frame = new Frame();
frame.data(data);

// modify the data
const newData = [[...], [...], [...], [...], ...];
frame.data(newData);
Enter fullscreen mode Exit fullscreen mode

header()

The header() method is used to modify the column names in the frame. It takes the same header argument as the constructor – which is an array of strings.

Note: If you use header method without passing any argument, it will reset the column names to default header (Remember: header is optional).

// modify the header
const newHeader = [...];
frame.header(newHeader);

// Reset the header to default
frame.header();

// You can use any empty value to reset the header to default, for example:
// frame.header('');
// frame.header(null);
// frame.header(undefined);
// frame.header([]);
Enter fullscreen mode Exit fullscreen mode

column()

The column() method is used to get the column data of a particular column. It takes the column name or the index as an argument. It can also take an array of column names or indexes as an argument to get multiple columns.

The column() method returns a new frame with extracted column data as the data of the frame. You can chain other frame methods on the returned frame.

Get a single column

// get a single column on Index 2 (Index starts from 0)
const column = frame.column(2);

// Alternatively, you can use the column name
const column = frame.column('Name');

// print the column
column.show();
Enter fullscreen mode Exit fullscreen mode

Get multiple columns

// get multiple columns on Index 2 and 3 (Index starts from 0)
const columns = frame.column([2, 3]);

// Alternatively, you can use the column names
const columns = frame.column(['Name', 'Age']);

// print the columns
columns.show();
Enter fullscreen mode Exit fullscreen mode

row()

The row() method is used to get the row data of a particular row. It takes the row index as an argument. It can also take an array of row indexes as an argument to get multiple rows.

The row() method returns a new frame with extracted row data as the data of the frame. You can chain other frame methods on the returned frame.

Get a single row

// get a single row on Index 2 (Index starts from 0)
const row = frame.row(2);

// print the row
row.show();
Enter fullscreen mode Exit fullscreen mode

Get multiple rows

// get multiple rows on Index 2 and 3 (Index starts from 0)
const rows = frame.row([2, 3]);

// print the rows
rows.show();
Enter fullscreen mode Exit fullscreen mode

find()

The find() method is used to find the rows that match the given condition. It takes a string or a number as an argument which is needed to be found in the frame. Optionally, it also takes an options object as as the second argument.

The valid options are defined below:

  • row: The row index to seach in. Can also be an array of row indexes.
  • column: The column name or index to search in. Can also be an array of column names or indexes.
  • strict: If true, the search will be performed on the exact value. If false, the search will be performed on the value as a substring. Default is false.

Hint: You can also combine the range() helper method to pass a range of rows or columns.

// find all the rows with value 'John' in column 'Name'
const row = frame.find('John', {column: 'Name'});

// find all the rows with value 'John' in columns 0, 1 and 2. Perform a strict search
const row = frame.find('John', {column: [0, 1, 2], strict: true});

// find all the rows with value 'John' in columns 0, 1 and 2 and rows 3, 4 and 5.
// Perform a non-strict search
const row = frame.find('John', {column: [0, 1, 2], row: [3, 4, 5], strict: false});
Enter fullscreen mode Exit fullscreen mode

sort()

The sort() method is used to sort the rows in the frame. It takes the column name or the index as an argument. It also takes an optional ascending or descending argument to sort the rows in ascending or descending order. Default is ascending.

Note: sort() method permanently modifies the frame. You can chain other frame methods on the returned frame.

// sort the rows in the frame with column 'Name' 
frame.sort('Name');

// sort the rows in the frame with column 'Name' in descending order
frame.sort('Name', 'descending');

// sort the rows in the frame with column index 0 in ascending order
frame.sort(0, 'ascending');
Enter fullscreen mode Exit fullscreen mode

show()

The show() method is used to print the frame. It takes no argument.

show() is a print method and it does not return a new frame and therefore it is not chainable.

// print the frame
frame.show();
Enter fullscreen mode Exit fullscreen mode

You can learn more methods at the official documentation

Helper Methods

Helper methods are methods that are used to help you with some common tasks. They are not chainable. They are not required to use the frame methods.

range()

range() is a helper method that is used to create a an array of numbers. Here are the arguments and their default values:

Argument Description Default Value
start The start of the range Required
end The end of the range Required
step The step size of the range 1
remove An array of numbers which should not be included in the range undefined

Note: The step and remove arguments are optional. If you do not provide it, step will be set to 1 and remove will be set to undefined.

Example

range(0, 10);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

range(0, 10, 2);
// [0, 2, 4, 6, 8, 10]

range(0, 10, 1, [1, 3, 5, 7, 9]);
// [0, 2, 4, 6, 8, 10]
Enter fullscreen mode Exit fullscreen mode

Example with frame

// Import Frame and range
import { Frame, range } from 'izuku';

// create a frame
const frame = new Frame([[...], [...], ...]);

// Get all columns from 2 to 6
const columns = frame.column(range(2, 6));
Enter fullscreen mode Exit fullscreen mode

You can learn more helper methods at the official documentation

Chaining Methods

Since, the row and column methods return a new frame, you can chain them together to get the data of multiple rows and columns. The following example shows how to get the data of multiple rows and columns.

The returned data is also a new frame and you can continue chaining other frame methods on it.

const data = [[...], [...], ...];
const header = [...];
const frame = new Frame(data, header);

// 1. get multiple rows on Index 2 and 3
// 2. then get the 'Name' and 'Age' columns of those rows
// 3. finally print the data
frame.row([2, 3]).column(['Name', 'Age']).show();
Enter fullscreen mode Exit fullscreen mode

Similarly you can chain more methods if required.

So, that's Izuku. It a new library. Go, show some love by starring the library at: https://github.com/luciferreeves/izuku.js. Also, if you can, contribute to the library or open an issue if you would like to see any features.

Discussion (0)