Apache pig 使用Apache Pig获取滚动日期值的计数

Apache pig 使用Apache Pig获取滚动日期值的计数,apache-pig,Apache Pig,我们如何使用Apache Pig实现: File : A 2014/10/01 A 2014/09/01 A 2014/08/01 A 2014/02/01 结果应该是3,因为我想使用记录组之间30天的滚动窗口来计算记录数。请找到解决方案,如果需要,我希望您可以做进一步的增强。尝试使用您的输入执行,并让我知道它是如何工作的 input.txt A 2014/12/01 A 2014/11/01 A 2014/10/01 A 2014/07/01 A 2014/05/01 A 2014

我们如何使用Apache Pig实现:

File :

A  2014/10/01
A  2014/09/01
A  2014/08/01
A  2014/02/01

结果应该是3,因为我想使用记录组之间30天的滚动窗口来计算记录数。

请找到解决方案,如果需要,我希望您可以做进一步的增强。尝试使用您的输入执行,并让我知道它是如何工作的

input.txt

A 2014/12/01
A 2014/11/01
A 2014/10/01
A 2014/07/01
A 2014/05/01
A 2014/04/01
B 2014/09/01
B 2014/07/01
B 2014/06/01
B 2014/02/01
C 2014/09/01
C 2014/07/01
C 2014/05/01
A 5
B 2
C 0
预期产出

A 2014/12/01
A 2014/11/01
A 2014/10/01
A 2014/07/01
A 2014/05/01
A 2014/04/01
B 2014/09/01
B 2014/07/01
B 2014/06/01
B 2014/02/01
C 2014/09/01
C 2014/07/01
C 2014/05/01
A 5
B 2
C 0
PigScript:

REGISTER rollingCount.jar;
A = LOAD 'input.txt' Using PigStorage(' ') AS (f1:chararray,f2:chararray);
B = GROUP A BY f1;
C = FOREACH B GENERATE mypackage.ROLLINGCOUNT(BagToString($1)) AS rollingCnt;
DUMP C;
(A,5)
(B,2)
(C,0)
脚本的输出:

REGISTER rollingCount.jar;
A = LOAD 'input.txt' Using PigStorage(' ') AS (f1:chararray,f2:chararray);
B = GROUP A BY f1;
C = FOREACH B GENERATE mypackage.ROLLINGCOUNT(BagToString($1)) AS rollingCnt;
DUMP C;
(A,5)
(B,2)
(C,0)
Java代码:
1.编译下面的java代码并创建jar文件名rollingCount.jar
2.我只是暂时写了代码,如果需要可以优化

ROLLINGCOUNT.java

package mypackage;

import java.io.*;
import org.apache.pig.EvalFunc;
import org.apache.pig.data.Tuple;
import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;
import java.util.*;

public class ROLLINGCOUNT extends EvalFunc<Integer> {
    public Integer exec(Tuple input) throws IOException {

        //Get the input String from request
        String inputString = (String)input.get(0);
        Date[] arrayOfDates = getArrayOfDate(inputString);
        long diffDays[] = getDaysBetweenList(arrayOfDates);
        int rollingCount = getRollingCount(diffDays);

        return rollingCount;
    }

    //Function to convert strings to array of dates
    static protected Date[] getArrayOfDate(String inputString)
    {
        //Get the 1st column, this will be the Id
        String ID = inputString.split("_")[0];

        //Replace all the Ids with Null, bcoz its a duplicate columns
        String modifiedString = inputString.replace(ID+"_","");

        //Split the string into multiple columns using '_' as delimiter
        String list[] = modifiedString.split("_");

        //Convert the string to list of  array dates
        Date[] dateList = new Date[list.length];
        int index=0;
        for (String dateString: list)
        {
            try
            {
                //Convert the date string to date object in the give format
                SimpleDateFormat dFormat = new SimpleDateFormat("yyyy/MM/dd");
                dateList[index++] = dFormat.parse(dateString);
            }
            catch(Exception e)
            {
                // error handling goes here
            }
        }
        return dateList;
    }

    //Function to get difference between two dates
    static protected long[] getDaysBetweenList(Date[] arrayOfDate)
    {
        long diffDays[] = new long[arrayOfDate.length-1];
        int cnt=0;      
        for (int index=0; index<arrayOfDate.length-1;index++)
        {
            long diff = Math.abs(arrayOfDate[index+1].getTime() - arrayOfDate[index].getTime());    
            long days = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
            diffDays[cnt++] = days;
        }
        return diffDays;
    }

    //Function to get the total rolling count   
    static protected int getRollingCount(long diffDays[])
    {
        int result =0;
        for(int index=0;index<diffDays.length;index++)
        {
            int cnt =0;
            //hardcoded the values of 30 and 31 days, may need to handle Feb month 28 or 29 days
            while((index<diffDays.length)&&((diffDays[index]==30)||(diffDays[index]==31)))
            {
                cnt++;
                index++;
            }
            if(cnt>0)
            {
                result = result + cnt+1;
            }       
        }
        return result;
    }
}
package-mypackage;
导入java.io.*;
导入org.apache.pig.EvalFunc;
导入org.apache.pig.data.Tuple;
导入java.text.simpleDataFormat;
导入java.util.concurrent.TimeUnit;
导入java.util.*;
公共类ROLLINGCOUNT扩展了EvalFunc{
公共整数执行(元组输入)引发IOException{
//从请求获取输入字符串
String inputString=(String)input.get(0);
日期[]arrayOfDates=getArrayOfDate(inputString);
long diffDays[]=GetDaysBetween列表(arrayOfDates);
int rollingCount=getRollingCount(diffDays);
返回滚动计数;
}
//函数将字符串转换为日期数组
静态保护日期[]getArrayOfDate(字符串输入字符串)
{
//获取第一列,这将是Id
字符串ID=inputString.split(“”)[0];
//将所有ID替换为Null,bcoz是重复的列
String modifiedString=inputString.replace(ID+“,”);
//使用“\u1”作为分隔符将字符串拆分为多列
字符串列表[]=modifiedString.split(“”);
//将字符串转换为数组日期列表
日期[]日期列表=新日期[list.length];
int指数=0;
用于(字符串日期字符串:列表)
{
尝试
{
//将日期字符串转换为给定格式的日期对象
SimpleDataFormat数据格式=新的SimpleDataFormat(“yyyy/MM/dd”);
dateList[index++]=dFormat.parse(日期字符串);
}
捕获(例外e)
{
//错误处理在这里进行
}
}
返回日期表;
}
//函数获取两个日期之间的差异
静态保护长[]GetDaysBetween列表(日期[]arrayOfDate)
{
long diffDays[]=新长[arrayOfDate.length-1];
int-cnt=0;

对于(int index=0;index该输入的预期输出是什么?是4还是5“A 2014-12-01 A 2014-11-01 A 2014-10-01 A 2014-08-01 A 2014-06-01 A 2014-04-01 A 2014-03-01”预期结果是5,因为2014-12-01 A 2014-11-01 A 2014-10-01有30天的滚动窗口和2014-04-01 A 2014-03-01。@Sivasakthi,你能帮我解决上面的问题吗?你的要求并不直接,到目前为止,我已经完成了每一天之间的差异,但总计数将有点挑战性。对于这个我可能需要写一个UDF。嘿,Saivasakthi……我的问题有任何的运气。我不能得到答案,请Helphi SIVA…谢谢你的答复。是的日期会在任何范围内,例如你在上面提到的日期。如果我们考虑30天滚动,则要求日期为EG:2014/10 / 01, 2014 / 10 / 02, 2014 / 10 / 03, 2014 / 09 / 01。它应该只考虑3个日期2014/10 / 01, 2014 / 10 / 02, 2014 / 10 /03.请检查这个链接,看看如何编译和链接jar到脚本。嗨,湿婆…我编译好了,非常感谢你的帮助。你岩石!我正在尝试各种组合现在。如果你有任何问题,我会向你开枪。嗨,Shiva……一个问题…ABO例如,我们将元组传递给UDF并获取计数。这是一种我们可以获取计数列表的方法吗?例如:对,我们将元组作为a_2014/01/01_a_2014/01/10_a_2014/02/01发送给UDF,我们从UDF中获取3个,我正在做进一步的研究,假设我们发送:a_2014/01/01/01_a_2014/01/10_a_2014/02/01_a_2014/04/01_A_2014_04_10是否有一种方法可以让UDF处理返回类似3,2的列表