简体   繁体   中英

Resample Time Series Data using Javascript and Mongodb

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM