Presentamos Danfo.js, una biblioteca similar a Pandas en JavaScript
martes, 22 de septiembre de 2020
Una publicación de los invitados Rising Odegua, investigador independiente, y Stephen Oni, de Data Science Nigeria
Danfo.js es una biblioteca de JavaScript de código abierto que proporciona estructuras de datos de alto rendimiento, intuitivas y fáciles de usar para manipular y procesar datos estructurados. Está inspirada en gran medida en la biblioteca de Pandas para Python y proporciona una interfaz y API similares. Esto significa que los usuarios que están familiarizados con la API de Pandas y conocen JavaScript pueden comenzar a usarla de inmediato.

Uno de los principales objetivos de Danfo.js es que los desarrolladores de JavaScript puedan aprovechar el procesamiento de datos, el aprendizaje automático y las herramientas de IA. Esto condice con nuestra visión y con la del equipo de TensorFlow.js, que es llevar el AA a la Web. Bibliotecas de código abierto como Numpy y Pandas revolucionan la facilidad de manipulación de datos en Python, y se han creado muchas herramientas en torno a ellas, lo que impulsa el efervescente ecosistema de AA en Python.
Danfo.js se compiló a partir de TensorFlow.js. Es decir, como Numpy potencia las operaciones aritméticas de Pandas, aprovechamos TensorFlow.js para potenciar nuestras operaciones aritméticas de bajo nivel.
En el siguiente ejemplo, te mostramos cómo crear un DataFrame de Danfo a partir de un objeto “tensor”:
Objeto de JSON a DataFrame:

Matriz de objeto con etiquetas de columna a DataFrame:

Puedes procesar fácilmente los datos faltantes (representados como NaN) en punto flotante, así como los datos en punto no flotante:

División inteligente basada en etiquetas, indexación sofisticada y consulta de grandes conjuntos de datos:

Herramientas sólidas de E/S para cargar datos de archivos planos (CSV y delimitados). De forma íntegra y en partes:

API interactiva, flexible e intuitiva para trazar objetos DataFrame y Series en el navegador:

Predicción de supervivencia del Titanic usando Danfo.js y Tensorflow.js
A continuación, mostramos una sencilla tarea de clasificación de extremo a extremo en la que se usan Danfo.js y TensorFlow.js. Utilizamos Danfo para la carga de datos, la manipulación y el procesamiento previo del conjunto de datos, y luego exportamos el objeto “tensor”.
Danfo.js es una biblioteca de JavaScript de código abierto que proporciona estructuras de datos de alto rendimiento, intuitivas y fáciles de usar para manipular y procesar datos estructurados. Está inspirada en gran medida en la biblioteca de Pandas para Python y proporciona una interfaz y API similares. Esto significa que los usuarios que están familiarizados con la API de Pandas y conocen JavaScript pueden comenzar a usarla de inmediato.

Danfo.js se compiló a partir de TensorFlow.js. Es decir, como Numpy potencia las operaciones aritméticas de Pandas, aprovechamos TensorFlow.js para potenciar nuestras operaciones aritméticas de bajo nivel.
Algunas de las principales características de Danfo.js
Danfo.js es rápida. Se compiló a partir de TensorFlow.js y admite tensores de forma preeestablecida. Eso significa que puedes cargar tensores en Danfo y convertir la estructura de datos de esta en tensores. Aprovechando estas dos bibliotecas, obtienes una biblioteca de procesamiento de datos por un lado (Danfo.js) y una potente biblioteca de AA por el otro (TensorFlow.js).En el siguiente ejemplo, te mostramos cómo crear un DataFrame de Danfo a partir de un objeto “tensor”:
const dfd = require("danfojs-node")
const tf = require("@tensorflow/tfjs-node")
let data = tf.tensor2d([[20,30,40], [23,90, 28]])
let df = new dfd.DataFrame(data)
let tf_tensor = df.tensor
console.log(tf_tensor);
tf_tensor.print()
Resultado:Tensor {
kept: false,
isDisposedInternal: false,
shape: [ 2, 3 ],
dtype: 'float32',
size: 6,
strides: [ 3 ],
dataId: {},
id: 3,
rankType: '2'
}
Tensor
[[20, 30, 40],
[23, 90, 28]]
Puedes convertir fácilmente matrices, JSON o parámetros Object en objetos de DataFrame para su manipulación. Objeto de JSON a DataFrame:
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()
Resultado:
Matriz de objeto con etiquetas de columna a DataFrame:
const dfd = require("danfojs-node")
obj_data = {'A': [“A1”, “A2”, “A3”, “A4”],
'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()
Resultado:
Puedes procesar fácilmente los datos faltantes (representados como NaN) en punto flotante, así como los datos en punto no flotante:
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)
let df_filled = df.fillna({columns: ["Name", "Count"], values: ["Apples",
df["Count"].mean()]})
df_filled.print()
Resultado:
División inteligente basada en etiquetas, indexación sofisticada y consulta de grandes conjuntos de datos:
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.loc({ rows: ["0:2"], columns: ["Name", "Price"] })
sub_df.print()
Resultado:
Herramientas sólidas de E/S para cargar datos de archivos planos (CSV y delimitados). De forma íntegra y en partes:
const dfd = require("danfojs-node")
//read the first 10000 rows
dfd.read_csv("file:///home/Desktop/bigdata.csv", chunk=10000)
.then(df => {
df.tail().print()
}).catch(err=>{
console.log(err);
})
En DataFrame y Series, se admiten funciones sólidas de procesamiento de datos como OneHotEncoders y LabelEncoders, y escaladores como StandardScaler y MinMaxScaler:const dfd = require("danfojs-node")
let data = ["dog","cat","man","dog","cat","man","man","cat"]
let series = new dfd.Series(data)
let encode = new dfd.LabelEncoder()
encode.fit(series)
let sf_enc = encode.transform(series)
let new_sf = encode.transform(["dog","man"])
Resultado:
API interactiva, flexible e intuitiva para trazar objetos DataFrame y Series en el navegador:
<!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/danfojs@0.1.1/dist/index.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="plot_div"></div>
<script>
dfd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
.then(df => {
var layout = {
title: 'A financial charts',
xaxis: {title: 'Date'},
yaxis: {title: 'Count'}
}
new_df = df.set_index({ key: "Date" })
new_df.plot("plot_div").line({ columns: ["AAPL.Open", "AAPL.High"], layout: layout
})
}).catch(err => {
console.log(err);
})
</script>
</body>
</html>
Resultado:
Predicción de supervivencia del Titanic usando Danfo.js y Tensorflow.js
A continuación, mostramos una sencilla tarea de clasificación de extremo a extremo en la que se usan Danfo.js y TensorFlow.js. Utilizamos Danfo para la carga de datos, la manipulación y el procesamiento previo del conjunto de datos, y luego exportamos el objeto “tensor”.
const dfd = require("danfojs-node")
const tf = require("@tensorflow/tfjs-node")
async function load_process_data() {
let df = await dfd.read_csv("https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv")
//A feature engineering: Extract all titles from names columns
let title = df['Name'].apply((x) => { return x.split(".")[0] }).values
//replace in df
df.addColumn({ column: "Name", value: title })
//label Encode Name feature
let encoder = new dfd.LabelEncoder()
let cols = ["Sex", "Name"]
cols.forEach(col => {
encoder.fit(df[col])
enc_val = encoder.transform(df[col])
df.addColumn({ column: col, value: enc_val })
})
let Xtrain,ytrain;
Xtrain = df.iloc({ columns: [`1:`] })
ytrain = df['Survived']
// Standardize the data with MinMaxScaler
let scaler = new dfd.MinMaxScaler()
scaler.fit(Xtrain)
Xtrain = scaler.transform(Xtrain)
return [Xtrain.tensor, ytrain.tensor] //return the data as tensors
}
A continuación, creamos una red neuronal simple usando TensorFlow.js.function get_model() {
const model = tf.sequential();
model.add(tf.layers.dense({ inputShape: [7], units: 124, activation: 'relu', kernelInitializer: 'leCunNormal' }));
model.add(tf.layers.dense({ units: 64, activation: 'relu' }));
model.add(tf.layers.dense({ units: 32, activation: 'relu' }));
model.add(tf.layers.dense({ units: 1, activation: "sigmoid" }))
model.summary();
return model
}
Por último, realizamos el entrenamiento cargando primero el modelo y los datos procesados como tensores. Esto puede insertarse directamente en la red neural. async function train() {
const model = await get_model()
const data = await load_process_data()
const Xtrain = data[0]
const ytrain = data[1]
model.compile({
optimizer: "rmsprop",
loss: 'binaryCrossentropy',
metrics: ['accuracy'],
});
console.log("Training started....")
await model.fit(Xtrain, ytrain,{
batchSize: 32,
epochs: 15,
validationSplit: 0.2,
callbacks:{
onEpochEnd: async(epoch, logs)=>{
console.log(`EPOCH (${epoch + 1}): Train Accuracy: ${(logs.acc * 100).toFixed(2)},
Val Accuracy: ${(logs.val_acc * 100).toFixed(2)}\n`);
}
}
});
};
train()
El lector notará que la API de Danfo es muy similar a la de Pandas, y un programador sin Javascript puede leer y entender el código de manera sencilla. Puedes encontrar el código fuente completo de la demostración anterior aquí (https://gist.github.com/risenW/f54e4e5b6d92e7b1b9b1f30e884ca83c).Comentarios finales
Con la maduración del aprendizaje automático en la Web, es imperativo contar con herramientas de ciencia de datos eficaces diseñadas específicamente para ese fin. Herramientas como Danfo.js permitirán que las aplicaciones basadas en la Web sean fácilmente compatibles con funciones de AA, lo que abrirá el espacio a un ecosistema de aplicaciones apasionantes. TensorFlow.js comenzó la revolución proporcionando capacidades de AA disponibles en Python, y esperamos que Danfo.js sea un socio eficiente en este proceso. ¡Ya queremos ver en qué se convierte Danfo.js! Esperemos que también se vuelva indispensable para la comunidad de la Web.- Juega con Danfo.js en CodePen
- Vínculo a la guía de introducción oficial
- Vínculo al repositorio de GitHub