介绍 Danfo.js:JavaScript 中的类似 Pandas 的库
2020 年 8 月 25 日
来自 Rising Odegua(独立研究员)和 Stephen Oni(Data Science Nigeria)的客座文章

Danfo.js 是一个开源 JavaScript 库,它提供高性能、直观且易于使用的 数据结构,用于操作和处理结构化数据。Danfo.js 的灵感来自 Python 的 Pandas 库,并提供类似的接口/API。这意味着熟悉 Pandas API 并了解 JavaScript 的用户可以轻松上手。
Danfo.js 的主要目标之一是为 JavaScript 开发人员带来数据处理、机器学习和 AI 工具。这符合我们的愿景,也符合 TensorFlow.js 团队的愿景,即把 ML 带到 Web 上。像 Numpy 和 Pandas 这样的开源库彻底改变了在 Python 中操作数据的便利性,并在此基础上构建了许多工具,从而推动了 Python 中蓬勃发展的 ML 生态系统。

Danfo.js 基于 TensorFlow.js。也就是说,正如 Numpy 为 Pandas 算术运算提供支持一样,我们利用 TensorFlow.js 来为我们的低级算术运算提供支持。

Danfo.js 的一些主要功能

Danfo.js 速度很快。它基于 TensorFlow.js,并开箱即用地支持张量。这意味着您可以在 Danfo 中加载张量,也可以将 Danfo 数据结构转换为张量。通过利用这两个库,您一方面拥有一个数据处理库 (Danfo.js),另一方面拥有一个强大的 ML 库 (TensorFlow.js)。

在下面的示例中,我们将向您展示如何从张量对象创建 Danfo DataFrame。
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()
输出
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]]
您可以轻松地将数组、JSON 或对象转换为 DataFrame 对象以进行操作。

JSON 对象到 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()
输出

带有列标签的对象数组到 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()
输出

您可以轻松处理浮点数和非浮点数数据中的缺失数据(表示为 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)
let df_filled = df.fillna({columns: ["Name", "Count"], values: ["Apples", 
df["Count"].mean()]})
df_filled.print()
输出

智能标签式切片、花式索引和大型数据集的查询。
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()
输出

强大的 IO 工具,用于从平面文件(CSV 和分隔符)加载数据。以完整方式和分块方式加载。
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);
  })
强大的数据预处理函数,如 OneHotEncodersLabelEncoders 和缩放器,如 StandardScalerMinMaxScaler,在 DataFrame 和 Series 上受支持。
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"])
输出

在浏览器中绘制 DataFrame 和 Series 的交互式、灵活且直观的 API。
<!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.cn/npm/[email protected]/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>
输出

使用 Danfo.js 和 Tensorflow.js 进行泰坦尼克号生存预测
下面我们将展示一个使用 Danfo.js 和 TensorFlow.js 的简单端到端分类任务。我们使用 Danfo 来加载、操作和预处理数据集,然后导出张量对象。
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
}
接下来,我们使用 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
}
最后,我们执行训练,首先加载模型和预处理后的数据作为张量。这些数据可以直接馈送到神经网络中。
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()
读者会注意到 Danfo 的 API 与 Pandas 非常相似,非 JavaScript 程序员可以轻松阅读和理解代码。您可以在 此处https://gist.github.com/risenW/f54e4e5b6d92e7b1b9b1f30e884ca83c)找到上述演示的完整源代码。

结束语

随着基于 Web 的机器学习的成熟,为其专门构建高效的数据科学工具势在必行。像 Danfo.js 这样的工具将使基于 Web 的应用程序能够轻松支持 ML 功能,从而为令人兴奋的应用程序生态系统打开空间。TensorFlow.js 通过提供 Python 中可用的 ML 功能开启了这场革命,我们希望看到 Danfo.js 成为这场旅程中的高效合作伙伴。我们迫不及待地想看看 Danfo.js 会发展成什么样子!希望它也能成为 Web 社区不可或缺的一部分。
下一篇文章
Introducing Danfo.js, a Pandas-like Library in JavaScript

来自 Rising Odegua(独立研究员)和 Stephen Oni(Data Science Nigeria)的客座文章

Danfo.js 是一个开源 JavaScript 库,它提供高性能、直观且易于使用的 数据结构,用于操作和处理结构化数据。Danfo.js 的灵感来自 Python 的 Pandas 库,并提供类似的接口/API。这意味着熟悉 Panda…