按频率对数据进行分组

时间:2013-04-03 14:41:41

标签: python group-by timestamp time-series

我做了一个代码,它在下面生成随机数,然后我将它们保存在csv中,如下图所示,我正在尝试游戏并按功能学习组。我希望例如通过时间戳来计算这些组的总和或平均值。我是Python的新手,我找不到任何地方可以开始。 Ulitmately我想做同样的但是1分钟或5分钟(从00:00:00开始每5分钟,在我的例子中没有足够的数据,但是这样做会像13:35:00到13:40:00这样做下一个13:40:00包括到13:45:00排除,等),我想我可以弄清楚从时间戳提取分钟部分1分钟,但5分钟似乎很复杂。不要求复制粘贴代码,但我不知道从哪里开始说实话。

Level   Timestamp
99  03/04/2013 13:37:20
98  03/04/2013 13:37:20
98  03/04/2013 13:37:20
99  03/04/2013 13:37:20
105 03/04/2013 13:37:20
104 03/04/2013 13:37:20
102 03/04/2013 13:37:21
102 03/04/2013 13:37:21
103 03/04/2013 13:37:22
82  03/04/2013 13:37:23
83  03/04/2013 13:37:23
82  03/04/2013 13:37:23
83  03/04/2013 13:37:23
54  03/04/2013 13:37:24
55  03/04/2013 13:37:24
54  03/04/2013 13:37:24
55  03/04/2013 13:37:24
56  03/04/2013 13:37:25
57  03/04/2013 13:37:25

2 个答案:

答案 0 :(得分:3)

可以使用itertools完成 http://docs.python.org/2/library/itertools.html#itertools.groupby

但要小心:

  

每次键值产生一个中断或新组   功能变化(这就是为什么通常需要排序   数据使用相同的键功能)。

示例用法:

如果您的数据已被处理为Level,timestamp pair的列表。

data = [(99, '03/04/2013 13:37:20'), (98,  '03/04/2013 13:37:20'), ...]

你想用5分钟间隔的数据AVG小组

data.sort(key=lambda i: i[1]) # sort with timestamp
results = []

def keyfunc(timestamp, interval = 5*60):
    # defined a key function.
    # 1. parse the datetime string to datetime object
    # 2. count the time delta (seconds)
    # 3. divided the time delta with interval, which is (6*60) here
    xt = datetime(2013, 4,3)
    dt = datetime.strptime(timestamp, '%d/%m/%Y %H:%M:%S')
    delta_second = int((dt - xt).total_seconds())
    normalize_second = (delta_second / interval) * interval
    return xt + timedelta(seconds=normalize_second)

for k, g in groupby(data, key=lambda i: keyfunc(i[1])):
    # k would be time interval "03/04/2013 13:30:00", "03/04/2013 13:35:00" .... 
    # g would be the level, timestamp pair belong to the interval
    avg_level = sum([x[0] for x in g]) / len(g)
    results.append((k, avg_level))

EDIT1

groupby函数中使用的keyfunc说明了如何将项目分组。 如果两个项具有相同的键功能返回值,则它们将被放置在同一组中。 (仅当这些项目被分类时)

>>> keyfunc('03/04/2013 13:37:20')
datetime.datetime(2013, 4, 3, 13, 35)

>>> keyfunc('03/04/2013 13:37:30')
datetime.datetime(2013, 4, 3, 13, 35)

# the return value are the same, so 03/04/2013 13:37:20 and 03/04/2013 13:37:30
# will be consider in the same group. 

答案 1 :(得分:0)

有几种方法可以解决这个问题,但你在时间上有效地“分档”。我会在几个步骤中接近它:

你不想用字符串操作自己解析时间,它会在你的脸上爆炸;相信我!将时间戳解析为日期时间对象(谷歌应该给你一个很好的答案)。一旦你拥有了它,你可以做很多有趣的事情,比如两次比较。

现在你有了datetime对象,你可以开始“bin”它们了。我将假设记录是有序的。从第一个记录的时间开始“03/04/2013 13:37:20”并在“03/04/2013 13:37:00”创建一个新的日期时间对象[提示:在datetime对象上设置秒= 0读入]。这是你的第一个“垃圾箱”的开始。现在将一分钟添加到您的开始日期时间[提示:endDT = startDT + timedelta(秒= 60)],这是您第一个垃圾箱的结束。

现在开始浏览你的记录,检查记录是否小于你的endDT,如果是,则将其添加到该bin的列表中。如果记录大于你的endDT,你就在下一个bin中。要启动新的bin,请在endDT中添加一分钟,然后创建一个新列表来保存这些项目,并在循环中继续进行。

完成循环后,您可以在列表上运行max / min / avg。理想情况下,您将列表存储在类似{datetimeObject:[34,23,45,23]}的字典中。它将使打印和分类变得容易。

这不是最有效/灵活/最酷的方式,但我认为这可能是最有帮助的。