PIG:计算纬度和经度对之间的最大距离

时间:2016-01-08 23:05:10

标签: python apache-pig

我有一个猪袋,按钥匙分组,其值是纬度和经度。我想计算每个键的任意两个(lat,long)对之间的最大距离;如果少于2则输出应为0.

例如,如果我的包是

{(1): (1.1, 1.1),
 (1): (2.1, 2.1),
 (1): (3.1, 3.1),
 (2): (1.1, 1.1)
}

我的回答是

{(1): 314 (km)
 (2): 0
}

计算两个(纬度,长度)对之间距离的公式为:

(((lat1 - lat2) * pi() * 3959 / 180)^2 + ((long1 - long2) * 2 * pi() * 3959 * cos(((lat2 + lat1) / 2) * .0174533) / 360)^2)^(1/2) 

有没有一种简单的方法来创建python udf来做到这一点?谢谢您的帮助。

2 个答案:

答案 0 :(得分:1)

检查我的github回购: https://github.com/csabakecskemeti/geo_clustering/tree/master/src/main/java/kecso/geotools/geodistance

这是用于地理距离计算的java UDF。您可以使用它来计算对的距离,而不是应用MAX函数。我希望这会有所帮助。

答案 1 :(得分:1)

以下是我想到的步骤:

  1. FLATTEN包。这将使用

    生成元组(在您的示例中)

    (1,1.1,1.1) (1,2.1,2.1) (1,3.1,3.1) (2,1.1,1.1)

  2. 执行TWICE以上的步骤,得到两个不同的名称:r1和r2。

  3. 通过关键字段加入r1和r2。这将为每个键创建一个笛卡尔积[/ p>

  4. 按键加入r1,按键加入r2

    这将导致

    (1,1.1,1.1,1,1.1,1.1)
    (1,1.1,1.1,1,2.1,2.1)
    (1,1.1,1.1,1,3.1,3.1)
    (1,2.1,2.1,1,1.1,1.1)
    (1,2.1,2.1,1,2.1,2.1)
    (1,2.1,2.1,1,3.1,3.1)
    (1,3.1,3.1,1,1.1,1.1)
    (1,3.1,3.1,1,2.1,2.1)
    (1,3.1,3.1,1,3.1,3.1)
    (2,1.1,1.1,2,1.1,1.1)
    

    此列表包含每个键的所有可能对。作为奖励,对于只有一个坐标的键,您还可以获得一对该坐标。

    1. 使用datafu中的HaversineDistInMiles UDF http://datafu.incubator.apache.org/docs/datafu/1.2.0/datafu/pig/geo/HaversineDistInMiles.html
    2. 计算每对坐标之间的距离。对于具有相同坐标的对,您将获得距离== 0。

      (datafu是来自LinkedIn的一套优秀的实用UDF。请在此处阅读:https://datafu.incubator.apache.org

      1. 按键分组,并为每个键生成MAX(距离)。这将为您提供英里的最大距离。乘以1.6093以获得KM的距离。
      2. 假设您的文件如下所示:

        1   {(1.1,1.1),(2.1,2.1),(3.1,3.1)}
        2   {(1.1,1.1)}
        

        使用这个猪脚本:

        register '/path/to/datafu-1.2.0.jar';
        a = LOAD 'pigcoords.tsv' using PigStorage() as (A1:int, B1:bag{T:tuple(longitude:double, latitude:double)});
        b = foreach a generate A1, FLATTEN(B1);
        c = foreach a generate A1, FLATTEN(B1);
        d = foreach (join b by A1, c by A1) generate $0..;
        op = FOREACH d GENERATE b::A1 as key, datafu.pig.geo.HaversineDistInMiles(b::B1::latitude, b::B1::longitude, c::B1::latitude, c::B1::longitude) as distance;
        res = FOREACH (group op by key) generate MAX(op.distance)*1.6093;
        dump res;