Getting Started
Installation guides for Node and Browser based environments, including a quick 10 minute walk through of danfo.js
Installation
There are three ways to install and use Danfo.js in your application
For Nodejs applications, you can install the danfojs-node version via package managers like yarn and npm:
npm install danfojs-node
or
yarn add danfojs-node
For client-side applications built with frameworks like React, Vue, Next.js, etc, you can install the danfojs version:
npm install danfojs
or
yarn add danfojs
For use directly in HTML files, you can add the latest script tag from JsDelivr:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script>
To play with Danfo.js in a Notebook-like environment, see Dnotebooks here or the VS-Code Nodejs notebook extension.
10 minutes to danfo.js
This is a short introduction to Danfo.js, and its flow is adapted from the official 10 minutes to Pandas
We will show you how to use danfo.js in a browser, client-side libraries, and Node.js environments. Most functions except plotting which require a DOM work the same way in all environments.
const dfd = require("danfojs-node")
//or using ES6
import * as dfd from "danfojs-node"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script>
</head>
<body>
<script>
//danfo is exposed on dfd namespace
s = new dfd.Series([1,2,3,4,5])
</script>
</body>
</html>
import * as dfd from "danfojs"
//import specific methods/classes
import { readCSV, DataFrame } from "danfojs"
Creating a DataFrame/Series
You can create a Series
by passing a list of values, letting Danfo.js create a default integer index:
import * as dfd from "danfojs-node"
s = new dfd.Series([1, 3, 5, undefined, 6, 8])
s.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
s = new dfd.Series([1, 3, 5, undefined, 6, 8])
s.print()
</script>
</body>
</html>
//output
╔═══╤══════════════════════╗
║ │ 0 ║
╟───┼──────────────────────╢
║ 0 │ 1 ║
╟───┼──────────────────────╢
║ 1 │ 3 ║
╟───┼──────────────────────╢
║ 2 │ 5 ║
╟───┼──────────────────────╢
║ 3 │ undefined ║
╟───┼──────────────────────╢
║ 4 │ 6 ║
╟───┼──────────────────────╢
║ 5 │ 8 ║
╚═══╧══════════════════════╝
Creating a Series
from a tensor
const dfd = require("danfojs-node")
const tf = dfd.tensorflow //Tensorflow.js is exportedfrom Danfojs
let tensor_arr = tf.tensor([12,34,56,2])
let s = new dfd.Series(tensor_arr)
s.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script>
<title>Document</title>
</head>
<body>
<script>
const tf = dfd.tensorflow //get tensorflow lib from danfo
let tensor_arr = tf.tensor([12,34,56,2])
let s = new dfd.Series(tensor_arr)
s.print()
</script>
</body>
</html>
╔═══╤════╗
║ 0 │ 12 ║
╟───┼────╢
║ 1 │ 34 ║
╟───┼────╢
║ 2 │ 56 ║
╟───┼────╢
║ 3 │ 2 ║
╚═══╧════╝
Creating a DataFrame
by passing a JSON object:
const dfd = require("danfojs-node")
json_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
df = new dfd.DataFrame(json_data)
df.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script>
<title>Document</title>
</head>
<body>
<script>
json_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
df = new dfd.DataFrame(json_data)
df.print()
</script>
</body>
</html>
Creating a DataFrame
from a 2D tensor
const dfd = require("danfojs-node")
const tf = dfd.tensorflow //Tensorflow.js is exported from Danfojs
let tensor_arr = tf.tensor2d([[12, 34, 2.2, 2], [30, 30, 2.1, 7]])
let df = new dfd.DataFrame(tensor_arr, {columns: ["A", "B", "C", "D"]})
df.print()
df.ctypes.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
json_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
df = new dfd.DataFrame(json_data)
df.print()
</script>
</body>
</html>
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C │ D ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 12 │ 34 │ 2.20000004768... │ 2 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 30 │ 30 │ 2.09999990463... │ 7 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
╔═══╤══════════════════════╗
║ │ 0 ║
╟───┼──────────────────────╢
║ A │ int32 ║
╟───┼──────────────────────╢
║ B │ int32 ║
╟───┼──────────────────────╢
║ C │ float32 ║
╟───┼──────────────────────╢
║ D │ int32 ║
╚═══╧══════════════════════╝
Creating a DataFrame
by passing a dictionary of objects with the same length
const dfd = require("danfojs-node")
// Danfojs v1.0.0 and above
dates = new dfd.dateRange({ start: '2017-01-01', end: "2020-01-01", period: 4, freq: "Y" })
console.log(dates);
obj_data = {'A': dates,
'B': ["bval1", "bval2", "bval3", "bval4"],
'C': [10, 20, 30, 40],
'D': [1.2, 3.45, 60.1, 45],
'E': ["test", "train", "test", "train"]
}
df = new dfd.DataFrame(obj_data)
df.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
dates = new dfd.dateRange({ start: '2017-01-01', end: "2020-01-01", period: 4, freq: "Y" })
console.log(dates);
obj_data = {'A': dates,
'B': ["bval1", "bval2", "bval3", "bval4"],
'C': [10, 20, 30, 40],
'D': [1.2, 3.45, 60.1, 45],
'E': ["test", "train", "test", "train"]
}
df = new dfd.DataFrame(obj_data)
df.print()
</script>
</body>
</html>
//output in console
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C │ D │ E ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 1/1/2017, 1:0... │ bval1 │ 10 │ 1.2 │ test ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 1/1/2018, 1:0... │ bval2 │ 20 │ 3.45 │ train ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 1/1/2019, 1:0... │ bval3 │ 30 │ 60.1 │ test ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 1/1/2020, 1:0... │ bval4 │ 40 │ 45 │ train ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
The columns of the resulting DataFrame
have different dtypes.
df.ctypes.print()
//output
╔═══╤═════════╗
║ A │ string ║
╟───┼─────────╢
║ B │ string ║
╟───┼─────────╢
║ C │ int32 ║
╟───┼─────────╢
║ D │ float32 ║
╟───┼─────────╢
║ E │ string ║
╚═══╧═════════╝
Creating a DataFrame
by passing an array of arrays. Index and column labels are automatically generated for you.
const dfd = require("danfojs-node")
arr_data = [["bval1", 10, 1.2, "test"],
["bval2", 20, 3.45, "train"],
["bval3", 30, 60.1, "train"],
["bval4", 35, 3.2, "test"]]
df = new dfd.DataFrame(arr_data)
df.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
arr_data = [["bval1", 10, 1.2, "test"],
["bval2", 20, 3.45, "train"],
["bval3", 30, 60.1, "train"],
["bval4", 35, 3.2, "test"]]
df = new dfd.DataFrame(arr_data)
df.print()
</script>
</body>
</html>
//output in console
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ 0 │ 1 │ 2 │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ bval1 │ 10 │ 1.2 │ test ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ bval2 │ 20 │ 3.45 │ train ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ bval3 │ 30 │ 60.1 │ train ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ bval4 │ 35 │ 3.2 │ test ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Viewing data
Here is how to view the top and bottom rows of the frame above:
df.head(2).print()
df.tail(2).print()
//output from head
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ 0 │ 1 │ 2 │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ bval1 │ 10 │ 1.2 │ test ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ bval2 │ 20 │ 3.45 │ train ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
//output from tail
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ 0 │ 1 │ 2 │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ bval3 │ 30 │ 60.1 │ train ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ bval4 │ 35 │ 3.2 │ test ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Display the index, columns:
const dfd = require('danfojs-node')
let dates = new dfd.dateRange({
start: "2017-01-01",
end: "2020-01-01",
period: 4,
freq: "Y",
});
let obj_data = {
A: dates,
B: ["bval1", "bval2", "bval3", "bval4"],
C: [10, 20, 30, 40],
D: [1.2, 3.45, 60.1, 45],
E: ["test", "train", "test", "train"],
};
let df = new dfd.DataFrame(obj_data);
df.print();
console.log(df.index);
console.log(df.columns);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
let dates = new dfd.dateRange({
start: "2017-01-01",
end: "2020-01-01",
period: 4,
freq: "Y",
});
let obj_data = {
A: dates,
B: ["bval1", "bval2", "bval3", "bval4"],
C: [10, 20, 30, 40],
D: [1.2, 3.45, 60.1, 45],
E: ["test", "train", "test", "train"],
};
let df = new dfd.DataFrame(obj_data);
df.print();
console.log(df.index);
console.log(df.columns)
</script>
</body>
</html>
//output
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C │ D │ E ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 1/1/2017, 1:00:… │ bval1 │ 10 │ 1.2 │ test ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 1/1/2018, 1:00:… │ bval2 │ 20 │ 3.45 │ train ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 1/1/2019, 1:00:… │ bval3 │ 30 │ 60.1 │ test ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 1/1/2020, 1:00:… │ bval4 │ 40 │ 45 │ train ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
[ 0, 1, 2, 3 ]
[ 'A', 'B', 'C', 'D', 'E' ]
DataFrame.tensor
returns a Tensorflow tensor representation of the underlying data. Note that Tensorflow tensors have one dtype for the entire array, while danfo DataFrames have one dtype per column.
For df
, our DataFrame
of all floating-point values, DataFrame.tensor
is fast and doesn’t require copying data.
const dfd = require("danfojs-node")
j son_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
let df = new dfd.DataFrame(json_data)
console.log(df.tensor);
//or
df.tensor.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
json_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
df = new dfd.DataFrame(json_data)
console.log(df.tensor);
//or
df.tensor.print()
</script>
</body>
</html>
//output
Tensor {
kept: false,
isDisposedInternal: false,
shape: [ 4, 4 ],
dtype: 'float32',
size: 16,
strides: [ 4 ],
dataId: {},
id: 0,
rankType: '2'
}
Tensor
[[0.4612, 4.2828302, -1.5089999, -1.1352 ],
[0.5112, -0.22863 , -3.39059 , 1.1632 ],
[0.6911, -0.82863 , -1.5059 , 2.1352 ],
[0.4692, -1.28863 , 4.5058999 , 4.1631999]]
Note
DataFrame.tensor
does not include the index or column labels in the output.
describe()
shows a quick statistic summary of your data:
const dfd = require("danfojs-node")
let json_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
let df = new dfd.DataFrame(json_data)
df.describe().print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
json_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
df = new dfd.DataFrame(json_data)
df.describe().print()
</script>
</body>
</html>
//output in console
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C │ D ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ count │ 4 │ 4 │ 4 │ 4 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ mean │ 0.533175 │ 0.4842349999999… │ -0.474897500000… │ 1.5816 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ std │ 0.1075428712963… │ 2.5693167249095… │ 3.4371471031498… │ 2.2005448052698… ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ min │ 0.4612 │ -1.28863 │ -3.39059 │ -1.1352 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ median │ 0.4901999999999… │ -0.528629999999… │ -1.50745 │ 1.6492 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ max │ 0.6911 │ 4.28283 │ 4.5059 │ 4.1632 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ variance │ 0.0115654691666… │ 6.6013884328999… │ 11.813980208691… │ 4.84239744 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Sorting by values (Defaults to ascending):
const dfd = require("danfojs")
let data = {"A": [-20, 30, 47.3, NaN],
"B": [34, -4, 5, 6] ,
"C": [20, 2, 3, 30] }
let df = new dfd.DataFrame(data)
df.sortValues("C", {inplace: true})
df.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
let data = {"A": [-20, 30, 47.3, NaN],
"B": [34, -4, 5, 6] ,
"C": [20, 2, 3, 30] }
let df = new dfd.DataFrame(data)
df.sortValues("C", {inplace: true})
df.print()
</script>
</body>
</html>
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 30 │ -4 │ 2 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 47.3 │ 5 │ 3 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ -20 │ 34 │ 20 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ NaN │ 6 │ 30 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Selection
Getting
Selecting a single column, which yields a Series
, equivalent to df.A
:
const dfd = require("danfojs-node")
json_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
df = new dfd.DataFrame(json_data)
df['A'].print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
json_data = [{ A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
{ A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
{ A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
{ A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 }]
df = new dfd.DataFrame(json_data)
df['A'].print()
</script>
</body>
</html>
//output
╔═══╤══════════════════════╗
║ │ A ║
╟───┼──────────────────────╢
║ 0 │ 0.4612 ║
╟───┼──────────────────────╢
║ 1 │ 0.5112 ║
╟───┼──────────────────────╢
║ 2 │ 0.6911 ║
╟───┼──────────────────────╢
║ 3 │ 0.4692 ║
╚═══╧══════════════════════╝
Selection by label
For getting a cross-section using a label:
const dfd = require("danfojs")
let data = { "Name": ["Apples", "Mango", "Banana", "Pear"] ,
"Count": [21, 5, 30, 10] ,
"Price": [200, 300, 40, 250] }
let df = new dfd.DataFrame(data, {index: ["a", "b", "c", "d"]})
df.print()
let sub_df = df.loc({rows: ["a", "c"]})
sub_df.print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ a │ Apples │ 21 │ 200 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ b │ Mango │ 5 │ 300 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ c │ Banana │ 30 │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ d │ Pear │ 10 │ 250 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
Shape: (2,3)
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ a │ Apples │ 21 │ 200 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ c │ Banana │ 30 │ 40 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
Selecting on a multi-axis by label:
const dfd = require("danfojs-node")
let data = { "Name": ["Apples", "Mango", "Banana", "Pear"] ,
"Count": [21, 5, 30, 10],
"Price": [200, 300, 40, 250] }
let df = new dfd.DataFrame(data)
df.print()
let sub_df = df.loc({ rows: [0,1], columns: ["Name", "Price"] })
sub_df.print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ Apples │ 21 │ 200 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 5 │ 300 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ Banana │ 30 │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ Pear │ 10 │ 250 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
Shape: (2,2)
╔═══╤═══════════════════╤═══════════════════╗
║ │ Name │ Price ║
╟───┼───────────────────┼───────────────────╢
║ 0 │ Apples │ 200 ║
╟───┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 300 ║
╚═══╧═══════════════════╧═══════════════════╝
Showing label slicing:
const dfd = require("danfojs-node")
let data = { "Name": ["Apples", "Mango", "Banana", "Pear"] ,
"Count": [21, 5, 30, 10],
"Price": [200, 300, 40, 250] }
let df = new dfd.DataFrame(data)
df.print()
let sub_df = df.loc({ rows: ["0:2"], columns: ["Name", "Price"] })
sub_df.print()
//before slicing
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ Apples │ 21 │ 200 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 5 │ 300 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ Banana │ 30 │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ Pear │ 10 │ 250 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
//after slicing
╔════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Price ║
╟────────────┼───────────────────┼───────────────────╢
║ 0 │ Apples │ 200 ║
╟────────────┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 300 ║
╚════════════╧═══════════════════╧═══════════════════╝
Selection by position
Select via the position of the passed integers:
const dfd = require("danfojs-node")
let data = { "Name": ["Apples", "Mango", "Banana", "Pear"] ,
"Count": [21, 5, 30, 10] ,
"Price": [200, 300, 40, 250] }
let df = new dfd.DataFrame(data)
let sub_df = df.iloc({rows: [1,3]})
sub_df.print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 5 │ 300 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ Pear │ 10 │ 250 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
By integer slices:
const dfd = require("danfojs-node")
let data = { "Name": ["Apples", "Mango", "Banana", "Pear"] ,
"Count": [21, 5, 30, 10] ,
"Price": [200, 300, 40, 250] }
let df = new dfd.DataFrame(data)
let sub_df = df.iloc({rows: ["1:3"]})
sub_df.print()
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 5 │ 300 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ Banana │ 30 │ 40 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
By lists of integer position locations:
const dfd = require("danfojs-node")
let data = { "Name": ["Apples", "Mango", "Banana", "Pear"] ,
"Count": [21, 5, 30, 10] ,
"Price": [200, 300, 40, 250] }
let df = new dfd.DataFrame(data)
let sub_df = df.iloc({rows: [1,3], columns: [0,2]})
sub_df.print()
╔═══╤═══════════════════╤═══════════════════╗
║ │ Name │ Price ║
╟───┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 300 ║
╟───┼───────────────────┼───────────────────╢
║ 3 │ Pear │ 250 ║
╚═══╧═══════════════════╧═══════════════════╝
For slicing rows explicitly:
const dfd = require("danfojs-node")
let data = { "Name": ["Apples", "Mango", "Banana", "Pear"] ,
"Count": [21, 5, 30, 10] ,
"Price": [200, 300, 40, 250] }
let df = new dfd.DataFrame(data)
let sub_df = df.iloc({rows: ["2:3"], columns: [":"]})
sub_df.print()
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ Banana │ 30 │ 40 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
For slicing columns explicitly:
const dfd = require("danfojs-node")
let data = { "Name": ["Apples", "Mango", "Banana", "Pear"] ,
"Count": [21, 5, 30, 10] ,
"Price": [200, 300, 40, 250] }
let df = new dfd.DataFrame(data)
let sub_df = df.iloc({rows: [":"], columns: ["1:2"]})
sub_df.print()
╔════════════╤═══════════════════╗
║ │ Count ║
╟────────────┼───────────────────╢
║ 0 │ 21 ║
╟────────────┼───────────────────╢
║ 1 │ 5 ║
╟────────────┼───────────────────╢
║ 2 │ 30 ║
╟────────────┼───────────────────╢
║ 3 │ 10 ║
╚════════════╧═══════════════════╝
Selection with Boolean Mask
You can select subsections from a DataFrame by a booelan condition mask. E.g. In the following code, we select and return only rows where the column Count
is greater than 10.
let data = {
"Name": ["Apples", "Mango", "Banana", "Pear"],
"Count": [21, 5, 30, 10],
"Price": [200, 300, 40, 250]
}
let df = new dfd.DataFrame(data)
let sub_df = df.iloc({ rows: df["Count"].gt(10) })
sub_df.print()
//output
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ Apples │ 21 │ 200 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ Banana │ 30 │ 40 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
A Boolean mask for filtering also works for multiple conditions using and
& or
functions. E.g, In the following code, we select and return only rows where the column Count
is greater than 10 and column Name
is equal to Apples
.
let sub_df = df.iloc({
rows: df["Count"].gt(10).and(df["Name"].eq("Apples")),
columns: [0]
})
sub_df.print()
//output
╔════════════╤═══════════════════╗
║ │ Name ║
╟────────────┼───────────────────╢
║ 0 │ Apples ║
╚════════════╧═══════════════════╝
Boolean Querying/Filtering
The best way to query data is to use a boolean mask just as we demonstrated above with iloc and loc. For example, in the following code, we use a condition parameter to query the DataFrame:
let data = {
"A": ["Ng", "Yu", "Mo", "Ng"],
"B": [34, 4, 5, 6],
"C": [20, 20, 30, 40]
}
let df = new dfd.DataFrame(data)
let query_df = df.query(df["B"].gt(5))
query_df.print()
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ Ng │ 34 │ 20 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ Ng │ 6 │ 40 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Querying by a boolean condition is supported from v0.3.0 and above. It also supports condition chaining as long as the final boolean mask is the same lenght as the DataFrame rows. For example in the following code, we use multiple chaining conditions:
let data = {
"A": ["Ng", "Yu", "Mo", "Ng"],
"B": [34, 4, 5, 6],
"C": [20, 20, 30, 40]
}
let query_df = df.query( df["B"].gt(5).and(df["C"].lt(0)))
query_df.print() //after query
//output
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ Ng │ 34 │ 20 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Adding a new column
Setting a new column automatically aligns the data by the indexes.
const dfd = require("danfojs-node")
let data = { "A": [30, 1, 2, 3] ,
"B": [34, 4, 5, 6] ,
"C": [20, 20, 30, 40] }
let df = new dfd.DataFrame(data)
df.print()
let new_col = [1, 2, 3, 4]
df.addColumn("D", new_col, { inplace: true }); //happens inplace
df.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
let data = { "A": [30, 1, 2, 3] ,
"B": [34, 4, 5, 6] ,
"C": [20, 20, 30, 40] }
let df = new dfd.DataFrame(data)
df.print()
let new_col = [1, 2, 3, 4]
df.addColumn({ "column": "D", "values": new_col, inplace: true }); //happens inplace
df.print()
</script>
</body>
</html>
//before adding column
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 30 │ 34 │ 20 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 1 │ 4 │ 20 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 2 │ 5 │ 30 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 3 │ 6 │ 40 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
//after adding column
Shape: (4,3)
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C │ D ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 1 │ 2 │ 3 │ 25 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 4 │ 5 │ 6 │ 35 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 20 │ 30 │ 40 │ 45 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 39 │ 89 │ 78 │ 55 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Missing data
NaN, null, and undefined represent missing data in Danfo.js. These values can be dropped or filled using some functions available in Danfo.js.
To drop any columns that have missing data:
const dfd = require("danfojs-node")
let data = [[1, 2, 3], [NaN, 5, 6], [NaN, 30, 40], [39, 20, 78]]
let cols = ["A", "B", "C"]
let df = new dfd.DataFrame(data, { columns: cols })
df.print()
let df_drop = df.dropNa({ axis: 0 })
df_drop.print()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
let data = [[1, 2, 3], [NaN, 5, 6], [NaN, 30, 40], [39, undefined, 78]]
let cols = ["A", "B", "C"]
let df = new dfd.DataFrame(data, { columns: cols })
df.print()
let df_drop = df.dropNa({axis: 0})
df_drop.print()
</script>
</body>
</html>
//Before dropping
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 1 │ 2 │ 3 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ NaN │ 5 │ 6 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ NaN │ 30 │ 40 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 39 │ 20 │ 78 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
//after dropping
╔════════════╤═══════════════════╤═══════════════════╗
║ │ B │ C ║
╟────────────┼───────────────────┼───────────────────╢
║ 0 │ 2 │ 3 ║
╟────────────┼───────────────────┼───────────────────╢
║ 1 │ 5 │ 6 ║
╟────────────┼───────────────────┼───────────────────╢
║ 2 │ 30 │ 40 ║
╟────────────┼───────────────────┼───────────────────╢
║ 3 │ 20 │ 78 ║
╚════════════╧═══════════════════╧═══════════════════╝
To drop row(s) with have missing data, set the axis to 1:
const dfd = require("danfojs-node")
let data = [[1, 2, 3], [NaN, 5, 6], [20, 30, 40], [39, 34, 78]]
let cols = ["A", "B", "C"]
let df = new dfd.DataFrame(data, { columns: cols })
df.print()
let df_drop = df.dropNa({ axis: 1 })
df_drop.print()
//Before dropping
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 1 │ 2 │ 3 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ NaN │ 5 │ 6 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 20 │ 30 │ 40 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 39 │ 34 │ 78 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
//after dropping
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 1 │ 2 │ 3 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 39 │ 20 │ 78 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Filling missing data:
const dfd = require("danfojs-node")
let data = {
"Name": ["Apples", "Mango", "Banana", NaN],
"Count": [NaN, 5, NaN, 10],
"Price": [200, 300, 40, 250]
}
let df = new dfd.DataFrame(data)
let df_filled = df.fillNa("Apples")
df_filled.print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ Apples │ Apples │ 200 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 5 │ 300 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ Banana │ Apples │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ Apples │ 10 │ 250 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
Filling missing values in specific columns with specific values:
const dfd = require("danfojs-node")
let data = {
"Name": ["Apples", "Mango", "Banana", NaN],
"Count": [NaN, 5, NaN, 10],
"Price": [200, 300, 40, 250]
}
let df = new dfd.DataFrame(data)
df.print()
let df_filled = df.fillNa(["Apples", df["Count"].mean()], { columns: ["Name", "Count"] })
df_filled.print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ Apples │ 7.5 │ 200 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ Mango │ 5 │ 300 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ Banana │ 7.5 │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ Apples │ 10 │ 250 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
To get the boolean mask where values are nan
.
const dfd = require("danfojs-node")
let data = {"Name":["Apples", "Mango", "Banana", undefined],
"Count": [NaN, 5, NaN, 10],
"Price": [200, 300, 40, 250]}
let df = new dfd.DataFrame(data)
df.isNa().print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Name │ Count │ Price ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ false │ true │ false ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ false │ false │ false ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ false │ true │ false ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ true │ false │ false ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
Operations
Stats
Operations, in general, exclude missing data.
Performing a descriptive statistic:
const dfd = require("danfojs-node")
data = [[11, 20, 3], [1, 15, 6], [2, 30, 40], [2, 89, 78]]
cols = ["A", "B", "C"]
let df = new dfd.DataFrame(data, { columns: cols })
df.print()
df.mean().print() //defaults to column (1) axis
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--danfojs CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script> <title>Document</title>
</head>
<body>
<script>
data = [[11, 20, 3], [1, 15, 6], [2, 30, 40], [2, 89, 78]]
cols = ["A", "B", "C"]
let df = new dfd.DataFrame(data)
df.print()
df.mean().print() //defaults to column axis
</script>
</body>
</html>
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ 0 │ 1 │ 2 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 11 │ 20 │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 1 │ 15 │ 6 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 2 │ 30 │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 2 │ 89 │ 78 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
╔═══╤════════════════════╗
║ 0 │ 11.333333333333334 ║
╟───┼────────────────────╢
║ 1 │ 7.333333333333333 ║
╟───┼────────────────────╢
║ 2 │ 24 ║
╟───┼────────────────────╢
║ 3 │ 56.333333333333336 ║
╚═══╧════════════════════╝
Same operation on the row axis:
const dfd = require("danfojs-node")
data = [[11, 20, 3], [1, 15, 6], [2, 30, 40], [2, 89, 78]]
cols = ["A", "B", "C"]
let df = new dfd.DataFrame(data)
df.print()
df.mean({ axis: 0 }).print() //row axis=0, column=1
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ 0 │ 1 │ 2 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 11 │ 20 │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 1 │ 15 │ 6 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 2 │ 30 │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 2 │ 89 │ 78 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
╔═══╤═══════╗
║ A │ 4 ║
╟───┼───────╢
║ B │ 38.5 ║
╟───┼───────╢
║ C │ 31.75 ║
╚═══╧═══════╝
Operations on objects with different dimensionality and need alignment. Danfo automatically broadcasts along the specified dimension.
const dfd = require("danfojs-node")
let data = { "Col1": [1, 4, 5, 1], "Col2": [3, 2, 0, 4] }
let df = new dfd.DataFrame(data)
let sf = new dfd.Series([4, 5])
let df_new = df.sub(sf, { axis: 1 })
df_new.print()
╔═══╤═══════════════════╤═══════════════════╗
║ │ Col1 │ Col2 ║
╟───┼───────────────────┼───────────────────╢
║ 0 │ -3 │ -2 ║
╟───┼───────────────────┼───────────────────╢
║ 1 │ 0 │ -3 ║
╟───┼───────────────────┼───────────────────╢
║ 2 │ 1 │ -5 ║
╟───┼───────────────────┼───────────────────╢
║ 3 │ -3 │ -1 ║
╚═══╧═══════════════════╧═══════════════════╝
Apply
Applying functions to the data along a specified axis. If axis = 1 (default), then the specified function (callable)
will be called with each row data, and vice versa:
const dfd = require("danfojs")
let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]
let cols = ["A", "B", "C"]
let df = new dfd.DataFrame(data, { columns: cols })
function sum_vals(col) {
return col.reduce((a, b) => a + b, 0);
}
let df_new = df.apply(sum_vals, { axis: 1 })
df_new.print()
//before applying
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 1 │ 2 │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 4 │ 5 │ 6 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 20 │ 30 │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 39 │ 89 │ 78 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
//after applying
╔═══╤═════╗
║ 0 │ 6 ║
╟───┼─────╢
║ 1 │ 15 ║
╟───┼─────╢
║ 2 │ 90 ║
╟───┼─────╢
║ 3 │ 206 ║
╚═══╧═════╝
Applying Element wise operations to the data:
You can use the applyMap
function if you need to apply a function to each element in the DataFrame. applyMap
works element-wise.
const dfd = require("danfojs-node")
let data = [[1, 2, 3], [4, 5, 6], [20, 30, 40], [39, 89, 78]]
let cols = ["A", "B", "C"]
let df = new dfd.DataFrame(data, { columns: cols })
function sum_vals(x) {
return x + 10
}
let df_new = df.applyMap(sum_vals)
df_new.print()
//before applying
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 1 │ 2 │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 4 │ 5 │ 6 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 20 │ 30 │ 40 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 39 │ 89 │ 78 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
//after applyMap
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ 11 │ 12 │ 13 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ 14 │ 15 │ 16 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ 30 │ 40 │ 50 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ 49 │ 99 │ 88 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
String Methods
Series is equipped with a set of string processing methods in the str attribute that make it easy to operate on each element of the array, as in the code snippet below. Note that pattern-matching in str generally uses JavaScript regular expressions by default (and in some cases always uses them).
const dfd = require("danfojs-node")
let s = new dfd.Series(['A', 'B', 'C', 'Aaba', 'Baca', 'CABA', 'dog', 'cat'])
let lower_s = s.str.toLowerCase()
lower_s.print()
╔═══╤══════════════════════╗
║ │ 0 ║
╟───┼──────────────────────╢
║ 0 │ a ║
╟───┼──────────────────────╢
║ 1 │ b ║
╟───┼──────────────────────╢
║ 2 │ c ║
╟───┼──────────────────────╢
║ 3 │ aaba ║
╟───┼──────────────────────╢
║ 4 │ baca ║
╟───┼──────────────────────╢
║ 5 │ caba ║
╟───┼──────────────────────╢
║ 6 │ dog ║
╟───┼──────────────────────╢
║ 7 │ cat ║
╚═══╧══════════════════════╝
See more string accessors here
Merge
Concat
danfo provides various methods for easily combining together Series and DataFrame objects with various kinds of set logic for the indexes and relational algebra functionality in the case of join / merge-type operations.
Concatenating DataFrame together with concat()
:
const dfd = require("danfojs-node")
let data = [['K0', 'k0', 'A0', 'B0'], ['k0', 'K1', 'A1', 'B1'],
['K1', 'K0', 'A2', 'B2'], ['K2', 'K2', 'A3', 'B3']]
let data2 = [['K0', 'k0', 'C0', 'D0'], ['K1', 'K0', 'C1', 'D1'],
['K1', 'K0', 'C2', 'D2'], ['K2', 'K0', 'C3', 'D3']]
let colum1 = ['Key1', 'Key2', 'A', 'B']
let colum2 = ['Key1', 'Key2', 'A', 'D']
let df1 = new dfd.DataFrame(data, { columns: colum1 })
let df2 = new dfd.DataFrame(data2, { columns: colum2 })
let com_df = dfd.concat({ dfList: [df1, df2], axis: 1 }) //along column axis
com_df.print()
╔════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Key1 │ Key2 │ A │ B │ Key11 │ Key21 │ A1 │ D ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ K0 │ k0 │ A0 │ B0 │ K0 │ k0 │ C0 │ D0 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ k0 │ K1 │ A1 │ B1 │ K1 │ K0 │ C1 │ D1 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ K1 │ K0 │ A2 │ B2 │ K1 │ K0 │ C2 │ D2 ║
╟────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ K2 │ K2 │ A3 │ B3 │ K2 │ K0 │ C3 │ D3 ║
╚════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Concatenate along row axis (0).
const dfd = require("danfojs-node")
let data = [['K0', 'k0', 'A0', 'B0'], ['k0', 'K1', 'A1', 'B1'],
['K1', 'K0', 'A2', 'B2'], ['K2', 'K2', 'A3', 'B3']]
let data2 = [['K0', 'k0', 'C0', 'D0'], ['K1', 'K0', 'C1', 'D1'],
['K1', 'K0', 'C2', 'D2'], ['K2', 'K0', 'C3', 'D3']]
let colum1 = ['Key1', 'Key2', 'A', 'B']
let colum2 = ['Key1', 'Key2', 'A', 'D']
let df1 = new dfd.DataFrame(data, { columns: colum1 })
let df2 = new dfd.DataFrame(data2, { columns: colum2 })
let com_df = dfd.concat({ dfList: [df1, df2], axis: 0 }) //along row axis
com_df.print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Key1 │ Key2 │ A │ B │ D ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ K0 │ k0 │ A0 │ B0 │ NaN ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ k0 │ K1 │ A1 │ B1 │ NaN ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ K1 │ K0 │ A2 │ B2 │ NaN ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ K2 │ K2 │ A3 │ B3 │ NaN ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 4 │ K0 │ k0 │ C0 │ NaN │ D0 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 5 │ K1 │ K0 │ C1 │ NaN │ D1 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 6 │ K1 │ K0 │ C2 │ NaN │ D2 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 7 │ K2 │ K0 │ C3 │ NaN │ D3 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Join
SQL style merges. See the Pandas Database style joining section for more info.
const dfd = require("danfojs-node")
let data = [['K0', 'k0', 'A0', 'B0'], ['k0', 'K1', 'A1', 'B1'],
['K1', 'K0', 'A2', 'B2'], ['K2', 'K2', 'A3', 'B3']]
let data2 = [['K0', 'k0', 'C0', 'D0'], ['K1', 'K0', 'C1', 'D1'],
['K1', 'K0', 'C2', 'D2'], ['K2', 'K0', 'C3', 'D3']]
let colum1 = ['Key1', 'Key2', 'A', 'B']
let colum2 = ['Key1', 'Key2', 'A', 'D']
let df1 = new dfd.DataFrame(data, { columns: colum1 })
let df2 = new dfd.DataFrame(data2, { columns: colum2 })
df1.print()
df2.print()
let merge_df = dfd.merge({ "left": df1, "right": df2, "on": ["Key1"], how: "inner" })
merge_df.print()
//first DataFrame
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Key1 │ Key2 │ A │ B ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ K0 │ k0 │ A0 │ B0 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ k0 │ K1 │ A1 │ B1 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ K1 │ K0 │ A2 │ B2 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ K2 │ K2 │ A3 │ B3 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
//Second DataFrame
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Key1 │ Key2 │ A │ D ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ K0 │ k0 │ C0 │ D0 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ K1 │ K0 │ C1 │ D1 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ K1 │ K0 │ C2 │ D2 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ K2 │ K0 │ C3 │ D3 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
//After inner join on column 'Key1'
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ Key1 │ Key2 │ A │ B │ Key2_1 │ A_1 │ D ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ K0 │ k0 │ A0 │ B0 │ k0 │ C0 │ D0 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ K1 │ K0 │ A2 │ B2 │ K0 │ C1 │ D1 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ K1 │ K0 │ A2 │ B2 │ K0 │ C2 │ D2 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ K2 │ K2 │ A3 │ B3 │ K0 │ C3 │ D3 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
See the merge section for more examples
Grouping
By “group by” we are referring to a process involving one or more of the following steps:
Splitting the data into groups based on some criteria
Applying a function to each group independently
Combining the results into a data structure
See the Grouping section.
const dfd = require("danfojs-node")
let data ={'A': ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B': ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C': [1,3,2,4,5,2,6,7],
'D': [3,2,4,1,5,6,7,8]
}
let df = new dfd.DataFrame(data)
let grp = df.groupby(["A"])
grp.get_groups(["foo"]).print()
grp.get_groups(["bar"]).print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C │ D ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ foo │ one │ 1 │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ foo │ two │ 2 │ 4 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ foo │ two │ 5 │ 5 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ foo │ one │ 6 │ 7 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 4 │ foo │ three │ 7 │ 8 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Shape: (3,4)
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C │ D ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ bar │ one │ 3 │ 2 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ bar │ three │ 4 │ 1 ║
╟───┼───────────────────┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ bar │ two │ 2 │ 6 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╧═══════════════════╝
Grouping and then applying thesum()
function to the resulting groups.
const dfd = require("danfojs-node")
let data = {
A: ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
B: ["one", "one", "two", "three", "two", "two", "one", "three"],
C: [1, 3, 2, 4, 5, 2, 6, 7],
D: [3, 2, 4, 1, 5, 6, 7, 8],
};
let df = new dfd.DataFrame(data);
let grp = df.groupby(["A"]);
grp.col(["C"]).sum().print();
╔═══╤═══════════════════╤═══════════════════╗
║ │ A │ C_sum ║
╟───┼───────────────────┼───────────────────╢
║ 0 │ foo │ 21 ║
╟───┼───────────────────┼───────────────────╢
║ 1 │ bar │ 9 ║
╚═══╧═══════════════════╧═══════════════════╝
Grouping by multiple columns forms a hierarchical index, and again we can apply thesum()
function.
const dfd = require("danfojs-node")
let data ={'A': ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B': ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C': [1,3,2,4,5,2,6,7],
'D': [3,2,4,1,5,6,7,8]
}
let df = new dfd.DataFrame(data)
let grp = df.groupby(["A","B"])
grp.col(["C"]).sum().print()
╔═══╤═══════════════════╤═══════════════════╤═══════════════════╗
║ │ A │ B │ C_sum ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 0 │ foo │ one │ 7 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 1 │ foo │ two │ 7 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 2 │ foo │ three │ 7 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 3 │ bar │ one │ 3 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 4 │ bar │ two │ 2 ║
╟───┼───────────────────┼───────────────────┼───────────────────╢
║ 5 │ bar │ three │ 4 ║
╚═══╧═══════════════════╧═══════════════════╧═══════════════════╝
Time series
danfo provides a simple but powerful, and efficient functionality for working with DateTime data. See the dt Accessors section.
const dfd = require("danfojs-node")
let data = new dfd.dateRange({"start":'2018-01', freq:'M', period:3})
let sf = new dfd.Series(data)
//print series
sf.print()
//print month names
sf.dt.monthName().print()
╔═══╤══════════════════════╗
║ │ 0 ║
╟───┼──────────────────────╢
║ 0 │ 1/1/2018, 1:00:00 AM ║
╟───┼──────────────────────╢
║ 1 │ 2/1/2018, 1:00:00 AM ║
╟───┼──────────────────────╢
║ 2 │ 3/1/2018, 1:00:00 AM ║
╚═══╧══════════════════════╝
╔═══╤══════════╗
║ 0 │ January ║
╟───┼──────────╢
║ 1 │ February ║
╟───┼──────────╢
║ 2 │ March ║
╚═══╧══════════╝
More Examples:
const dfd = require("danfojs-node")
let data = new dfd.dateRange({"start":'2018-01', freq:'M', period:3})
let sf = new dfd.Series(data)
//print series
sf.print()
//print week day names
sf.dt.dayOfWeekName().print()
╔═══╤══════════════════════╗
║ │ 0 ║
╟───┼──────────────────────╢
║ 0 │ 1/1/2018, 1:00:00 AM ║
╟───┼──────────────────────╢
║ 1 │ 2/1/2018, 1:00:00 AM ║
╟───┼──────────────────────╢
║ 2 │ 3/1/2018, 1:00:00 AM ║
╚═══╧══════════════════════╝
╔═══╤══════════╗
║ 0 │ Monday ║
╟───┼──────────╢
║ 1 │ Thursday ║
╟───┼──────────╢
║ 2 │ Thursday ║
╚═══╧══════════╝
Plotting
See the Plotting docs.
We currently support Plotly.js for plotting. In the future, we plan other JS plotting libraries like Vega, D3.
Using the plot
API, you can make interactive plots from DataFrame and Series. Plotting only works in the browser/client-side version of Danfo.js, and requires an HTML div to display plots.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="plot_div"></div>
<script>
dfd.readCSV(
"https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv"
)
.then((df) => {
let layout = {
title: "A financial charts",
xaxis: {
title: "Date",
},
yaxis: {
title: "Count",
},
};
let config = {
columns: ["AAPL.Open", "AAPL.High"],
};
let new_df = df.setIndex({ column: "Date" });
new_df.plot("plot_div").line({ config, layout });
})
.catch((err) => {
console.log(err);
});
</script>
</body>
</html>
On a DataFrame, the plot()
method exposes various plot types. And by default, all columns are plotted unless specified otherwise.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.plot.ly/plotly-1.2.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="plot_div"></div>
<script>
df = new dfd.DataFrame({'pig': [20, 18, 489, 675, 1776],
'horse': [4, 25, 281, 600, 1900]}, {index: [1990, 1997, 2003, 2009, 2014]})
df.plot("plot_div").line()
</script>
</body>
</html>
Getting data in/out
CSV
Convert any DataFrame to csv format.
In NodeJs, if a file path is specified, then the CSV is saved to the path, else it is returned as a string.
In the browser, you can automatically download the file as CSV by setting the download
paramater to true
.
const dfd = require("danfojs-node")
let data = {
"Abs": [20.2, 30, 47.3],
"Count": [34, 4, 5],
"country code": ["NG", "FR", "GH"]
}
let df = new dfd.DataFrame(data)
const csv = dfd.toCSV(df)
console.log(csv);
//output
Abs,Count,country code
20.2,34,NG
30,4,FR
47.3,5,GH
dfd.toCSV(df, {filePath: "testOut.csv" }) //writes to file system in Nodejs
dfd.toCSV(df, {fileName: "testOut", download: true }) //downloads the file in browser version
Abs,Count,country code
20.2,34,NG
30,4,FR
47.3,5,GH
The readCSV method can read CSV files from local disk, or over the internet. Both full and relative paths are supported. For example, to read a CSV file at the path /home/Desktop/titanic.csv, you can do the following:
const dfd = require("danfojs")
dfd.readCSV("/home/Desktop/titanic.csv")
.then(df => {
//do something with the CSV file
df.head().print()
}).catch(err=>{
console.log(err);
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/bundle.min.js"></script>
<title>Document</title>
</head>
<body>
<script>
dfd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
.then(df => {
//do something like display descriptive statistics
df.describe().print()
}).catch(err => {
console.log(err);
})
</script>
</body>
</html>
JSON
Writing to JSON format
const dfd = require("danfojs-node")
let data = {
"Abs": [20.2, 30, 47.3],
"Count": [34, 4, 5],
"country code": ["NG", "FR", "GH"]
}
let df = new dfd.DataFrame(data)
const json = dfd.toJSON(df)
console.log(json);
//output
[
{ Abs: 20.2, Count: 34, 'country code': 'NG' },
{ Abs: 30, Count: 4, 'country code': 'FR' },
{ Abs: 47.3, Count: 5, 'country code': 'GH' }
]
const json = dfd.toJSON(df, {format: "row"})
console.log(json);
//output
{
Abs: [ 20.2, 30, 47.3 ],
Count: [ 34, 4, 5 ],
'country code': [ 'NG', 'FR', 'GH' ]
}
Last updated