使用Javascript / Node.js对时间序列或数据集进行重新采样

18

我需要在node.js中重新采样时间序列。所以我想知道在javascript中是否有类似于Python中的pandas的工具?

假设我有一个类似于这个示例的数据:

[{
    "time": "28-09-2018 21:29:04",
    "value1": 1280,
    "value2": 800
},
{   
    "time": "28-09-2018 21:38:56",
    "value1": 600,
    "value2": 700
},
{
    "time": "29-09-2018 10:40:00",
    "value1": 1100,
    "value2": 300
},
{
    "time": "29-09-2018 23:50:48",
    "value1": 140,
    "value2": 300
}]
在Python中,我会将这些数据放入一个pandas的数据框中,然后重新采样为另一个采样率的新数据框。例如:重新采样为每日数据。
import pandas
df = pandas.DataFrame(...)
df_days = df.resample('1440min').apply({'value1':'sum', 'value2':'sum'}).fillna(0)

那么我的新数据可能看起来像这样:

[{
    "time": "28-09-2018 00:00:00",
    "value1": 1880,
    "value2": 1500
},
{   
    "time": "29-09-2018 00:00:00",
    "value1": 1240,
    "value2": 600
}]

node.js / javascript 中,一般来说最好的方法是什么?


可能是 Python Pandas equivalent in JavaScript 的重复问题。 - Maor Refaeli
你找到解决这个问题的方法了吗? - user299791
是的,我将数据导出为Excel表格,然后执行一个Python脚本,该脚本加载数据并对其进行重新采样。如果您愿意,我可以发布代码。不幸的是,我找不到一个本地的Node.js解决方案。 - sunwarr10r
@baermathias 我也在尝试做类似的事情,你能否分享一下代码? - koper89
2个回答

2

我认为您不需要使用node.js/JS库来完成此任务。您想要实现的目标可以通过使用reduce函数来完成。

var a = [{
    "time": "28-09-2018 21:29:04",
    "value1": 1280,
    "value2": 800
},
{   
    "time": "28-09-2018 21:38:56",
    "value1": 600,
    "value2": 700
},
{
    "time": "29-09-2018 10:40:00",
    "value1": 1100,
    "value2": 300
},
{
    "time": "29-09-2018 23:50:48",
    "value1": 140
}];

var b = Object.values(a.reduce((container, current) => {
  var date = current['time'].substring(0, 10);
  if (!container[date])
    container[date] = {time: date + ' 00:00:00', value1: current['value1'] || 0, value2: current['value2'] || 0};
  else {
    container[date]['value1'] += current['value1'] || 0;
    container[date]['value2'] += current['value2'] || 0;
  }
  return container;
}, {}));

该函数创建一个以日期为键并聚合数值的对象。需要注意在该对象中日期是否存在。使用|| 0可以处理属性不在元素中的情况,防止出现错误;使用Object.values提取值以获得数组。由于你将日期用作字符串,我将它们视为字符串处理。如果它们是日期对象,则需要调整声明date的常规部分。
顺便提一下,像往常一样,您可以使用['value1'].value1在js中引用prop。我坚持使用更熟悉的Python语法,因为已经提到过。
当然,这只是一个每日重新采样的例子,如果您需要更大/更小的配额,则必须处理日期。假设我们想模拟12小时重新采样,那么您可以编写:
var resample = 12;
var b = Object.values(a.reduce((container, current) => {
  var date = new Date(current['time'].replace(/(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/, '$3-$2-$1T$4:$5:$6'));
  date.setHours(Math.floor(date.getHours() / resample) * resample);
  date.setMinutes(0);
  date.setSeconds(0);
  if (!container[date.toString()])
    container[date.toString()] = {time: date, value1: current['value1'] || 0, value2: current['value2'] || 0};
  else {
    container[date.toString()]['value1'] += current['value1'] || 0;
    container[date.toString()]['value2'] += current['value2'] || 0;
  }
  return container;
}, {}));

那个正则表达式 replace 是因为日期不是ISO格式,你可以使用库来处理,比如说moment或者其他的库,我只是想展示一下仅用普通JS也是可以完成的。
在使用JS日期时,请记住一件事情:如果您正在使用浏览器,则时区为客户端的时区;如果您在服务器上,则时区与服务器相同。如果time是没有时区限制的,那么在本地时区中管理所有内容应该没有问题。

0

简单的方法

  1. 非常简单的flask应用程序,可以为您处理pandas处理
  2. 使用简单的JQuery AJAX。

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
</head>
<body>
    <main id="main">
        <section id="data-section">
            <h2>Data</h2>
            <div id="data"/>
        </section>
    </main>
</body>
<script>
    function apicall(url, data) {
        $.ajax({
            type:"POST", url:url, data:{data:JSON.stringify(data)},
            success: (data) => { $("#data").text(JSON.stringify(data)); }
        });
    }
    data = [{"time": "28-09-2018 21:29:04","value1": 1280,"value2": 800},{"time": "28-09-2018 21:38:56","value1": 600,"value2": 700},{"time": "29-09-2018 10:40:00","value1": 1100,"value2": 300},
            {"time": "29-09-2018 23:50:48","value1": 140,"value2": 300}];
    window.onload = function () {
        apicall("/handle_data", data);
    }
</script>
</html>

Flask 应用

import pandas as pd, json
from flask import Flask, redirect, url_for, request, render_template, Response

app = Flask(__name__)

@app.route('/')
@app.route('/home')
def home():
    return render_template('home.html')

@app.route('/handle_data', methods=["POST"])
def handle_data():
    df = pd.DataFrame(json.loads(request.form.get("data")))
    df["time"] = pd.to_datetime(df["time"])
    df.set_index("time", inplace=True)
    df = df.resample('1440min').apply({'value1':'sum', 'value2':'sum'}).fillna(0)
    return Response(json.dumps(df.to_dict(orient="records")),
                    mimetype="text/json")

if __name__ == '__main__':
    app.run(debug=True, port=3000)

输出

enter image description here


2
这不是对问题的回答。它可能使用JavaScript,但问题是关于一个类似于pandas用于聚合的JS库的。 - Sid Kwakkel
1
@SidKwakkel 这是一个全栈答案。它非常简单,可以构建和部署到任何云堆栈(AWS EB、GCloud、Azure)。有效的异构微服务。同质化解决方案往往更加复杂。 - Rob Raymond
不错的想法,这甚至可以成为一个云函数。 - Gavin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接