【问题标题】:Pig 0.11.1 - Count groups in a time rangePig 0.11.1 - 在一个时间范围内计数组
【发布时间】:2013-08-02 23:11:23
【问题描述】:

我有一个数据集 A,它包含时间戳、访问者、URL:

(2012-07-21T14:00:00.000Z, joe, hxxp:///www.aaa.com) 
(2012-07-21T14:01:00.000Z, mary, hxxp://www.bbb.com) 
(2012-07-21T14:02:00.000Z, joe, hxxp:///www.aaa.com) 

我想在 10 分钟的时间窗口内测量每个 URL 的每个用户的访问次数,但作为一个按分钟递增的滚动窗口。输出将是:

(2012-07-21T14:00 to 2012-07-21T14:10, joe, hxxp://www.aaa.com, 2)
(2012-07-21T14:01 to 2012-07-21T14:11, joe, hxxp://www.aaa.com, 1)

为了使算术简单,我将时间戳更改为一天中的分钟,如下所示:

(840, joe, hxxp://www.aaa.com) /* 840 = 14:00 hrs x 60 + 00 mins) */

为了通过移动时间窗口迭代“A”,我创建了一个包含一天中分钟数的数据集 B:

(0)
(1)
(2)
.
.
.
.
(1440)

理想情况下,我想做这样的事情:

A = load 'dataset1' AS (ts, visitor, uri)
B = load 'dataset2' as (minute)

foreach B {
C = filter A by ts > minute AND ts < minute + 10;
D = GROUP C BY (visitor, uri);
foreach D GENERATE group, count(C) as mycnt;
}

DUMP B;

我知道“FOREACH”循环中不允许使用“GROUP”,但是否有解决方法可以达到相同的结果?

谢谢!

【问题讨论】:

    标签: hadoop mapreduce range apache-pig


    【解决方案1】:

    也许你可以做这样的事情?

    注意:这取决于您为整数日志创建的分钟数。如果不是,那么您可以四舍五入到最接近的分钟。

    myudf.py

    #!/usr/bin/python
    
    @outputSchema('expanded: {(num:int)}')
    def expand(start, end):
            return [ (x) for x in range(start, end) ]
    

    myscript.pig

    register 'myudf.py' using jython as myudf ;
    
    -- A1 is the minutes. Schema:
    -- A1: {minute: int}
    -- A2 is the logs. Schema:
    -- A2: {minute: int,name: chararray}
    -- These schemas should change to fit your needs.
    
    B = FOREACH A1 GENERATE minute, 
                            FLATTEN(myudf.expand(minute, minute+10)) AS matchto ;
    -- B is in the form:
    -- 1 1
    -- 1 2
    -- ....
    -- 2 2
    -- 2 3
    -- ....
    -- 100 100
    -- 100 101
    -- etc.
    
    -- Now we join on the minute in the second column of B with the 
    -- minute in the log, then it is just grouping by the minute in
    -- the first column and name and counting
    C = JOIN B BY matchto, A2 BY minute ;
    D = FOREACH (GROUP C BY (B::minute, name)) 
                GENERATE FLATTEN(group), COUNT(C) as count ;
    

    我有点担心较大日志的速度,但它应该可以工作。如果您需要我解释任何事情,请告诉我。

    【讨论】:

    • 非常感谢。那工作得很好。抱歉,我没有足够的声望点来提升这个解决方案。我不确定这是慢还是快,因为我没有等效的逻辑可以在我的集群上进行比较:) 无论如何,管理员都在对我大喊大叫,所以这很好。顺便说一句,/return [ (x) for x in range(start + 1, end) ]/ 应该是 /return [ (x) for x in range(start, end) ]/ 因为一天中的分钟从 0 开始。
    • @JoeNate 很好地抓住了射程的起点。乐意效劳。 :)
    【解决方案2】:
    A = load 'dataSet1' as (ts, visitor, uri);
    houred = FOREACH A GENERATE user, org.apache.pig.tutorial.ExtractHour(time) as hour, uri;
    hour_frequency1 = GROUP houred BY (hour, user);
    

    这样的事情应该会有所帮助 ExtractHour 是一个 UDF,您可以为所需的 Duration 创建类似的内容。 然后按小时分组,然后按用户分组 您可以使用 GENERATE 进行计数。

    http://pig.apache.org/docs/r0.7.0/tutorial.html

    【讨论】:

    • 我认为这只会给我每个用户每小时的频率。它不会给我每个可变时间段的频率(例如,每 10 分钟),也不是滚动频率(例如,按分钟)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 2015-12-13
    相关资源
    最近更新 更多