Resample Time Series Data using Javascript and Mon

2019-03-31 21:30发布

A data set of time series data needs to be turned from one with irregular time intervals to a regular time series, probably using interpolation and and resampling.

Python's pandas.Dataframe.resample is a function that will do this. Can Javascript do the same? The time series data set is stored in Mongodb.

1条回答
萌系小妹纸
2楼-- · 2019-03-31 22:13

It is kind of possible. Keep in mind that Pandas is a library built explicitly for those kind of tasks, and a beast at it, while MongoDB is meant to be a database. But chances are high that the following will suit your needs, if one ignores your probable need for using interpolation:

Assuming that you have the following data stored in a MongoDB collection named devices

/* 0 */
{
    "_id" : ObjectId("543fc08ccf1e8c06c0288802"),
    "t" : ISODate("2014-10-20T14:56:44.097+02:00"),
    "a" : "192.168.0.16",
    "i" : 0,
    "o" : 32
}

/* 1 */
{
    "_id" : ObjectId("543fc08ccf1e8c06c0288803"),
    "t" : ISODate("2014-10-20T14:56:59.107+02:00"),
    "a" : "192.168.0.16",
    "i" : 14243,
    "o" : 8430
}

and so on...

which, in this case, is sampled at around every 15 seconds, but it could as well be irregularly. If you want to resample it to a 5 minute boundary for a certain day, then you should do the following:

var low = ISODate("2014-10-23T00:00:00.000+02:00")
var high = ISODate("2014-10-24T00:00:00.000+02:00")
var interval = 5*60*1000;
db.devices.aggregate([
  {$match: {t:{$gte: low, $lt: high}, a:"192.168.0.16"}},
  {$group: {
     _id:{
       $subtract: ["$t", {
         $mod: [{
           $subtract: ["$t", low]
         }, interval]
       }]
     },
     total: {$sum: 1},
     incoming: {$sum: "$i"},
     outgoing: {$sum: "$o"},
    }
  },
  {
    $project: {
      total: true,
      incoming: true,
      outgoing: true,
      incoming_avg: {$divide: ["$incoming", "$total"]},
      outgoing_avg: {$divide: ["$outgoing", "$total"]},
    },
  },
  {$sort: {_id : 1}}
])

This will result in something like this

{
    "result" : [ 
        {
            "_id" : ISODate("2014-10-23T07:25:00.000+02:00"),
            "total" : 8,
            "incoming" : 11039108,
            "outgoing" : 404983,
            "incoming_avg" : 1379888.5,
            "outgoing_avg" : 50622.875
        }, 
        {
            "_id" : ISODate("2014-10-23T07:30:00.000+02:00"),
            "total" : 19,
            "incoming" : 187241,
            "outgoing" : 239912,
            "incoming_avg" : 9854.78947368421,
            "outgoing_avg" : 12626.94736842105
        }, 
        {
            "_id" : ISODate("2014-10-23T07:35:00.000+02:00"),
            "total" : 17,
            "incoming" : 22420099,
            "outgoing" : 1018766,
            "incoming_avg" : 1318829.352941176,
            "outgoing_avg" : 59927.41176470588
        },
        ...

If you want to discard the total incoming, then just leave the line out in the $project stage. The incoming_average is just an example of how to compute the average, in case your stored data is something like what rrdtool names a gauge (temperature, cpu, sensor data). If you're only after the sum aggregated in that time inverval, that is the incoming and outgoing field, then you can leave the entire $project stage out. It is only there to compute the average of the time interval.

See Mongo aggregation of ISODate into 45 minute chunks

查看更多
登录 后发表回答