如何利用Spark清洗数据?连续采样点数据的分析和删除!

houyafan 2016-11-14 03:31:41
+---------+-------------+------------+--------------------+----------+---------+-----+---------+---------+------+----+
|CENTER_ID| SIM_CODE|VEHICLE_CODE| GPS_TIME| LONGITUDE| LATITUDE|SPEED|VEH_STATE|GPS_STATE|ASPECT|note|
+---------+-------------+------------+--------------------+----------+---------+-----+---------+---------+------+----+
| QH|8613436770173| 浜珺N0600|2013-02-05 23:07:...| 116.39143| 39.9562| 0| 0| 0| 0| CZ|
| QH|8613911743873| 浜珺L6515|1990-11-27 19:31:...| 116.50256| 40.01292| 0| 0| 0| 0| CZ|
| QH|8613466436920| 浜珺Q7646|2013-02-05 23:07:...| 116.42857| 39.91751| 57| 57| 57| 57| CZ|
| QH|8613436743617| \N|2013-02-05 23:07:...| 116.40949| 39.86623| 0| 0| 0| 0| N|
| QH|8613466448087| 浜珺P1939|2013-02-05 23:08:...| 116.34241| 39.86377| 0| 0| 0| 0| CZ|
| QH|8613910943251| 浜珺M0634|2013-02-05 23:08:...| 116.28325| 39.9196| 0| 0| 0| 0| CZ|
| QH|8613436797347| 浜珺N1303|2013-02-05 23:07:...| 116.46843| 39.8749| 61| 61| 61| 61| CZ|
| ZHTC| 658151555052| 浜珺R2613|2013-02-05 23:59:...|116.446243|39.873974| 0| 0| 1| 0| CZ|
| ZHTC| 658151554952| 浜珺R2603|2013-02-05 23:59:...|116.449593|39.969357| 0| 0| 1| 40| CZ|
| QH|8613436733317| 浜珺Q4665|2013-02-05 23:07:...| 116.34068| 39.93797| 0| 0| 0| 0| CZ|
| QH|8613488638659| 浜珺N5544|2013-02-05 23:07:...| 116.42714| 39.947| 56| 56| 56| 56| CZ|
| ZHTC| 657658565556| 浜珺M9767|2013-02-06 00:14:...|116.418465|39.971001| 0| 0| 0| 177| CZ|
| ZHTC| 658054564949| 浜珺Q5700|2013-02-05 23:59:...|116.491478|39.997429| 54| 0| 1| 138| CZ|
| QH|8613466431941| 浜珺N9301|2013-02-05 23:08:...| 116.44119| 39.99269| 54| 54| 54| 54| CZ|
| ZHTC| 658051505257| 浜珺Q2138|2013-02-05 23:59:...|116.404152|39.855373| 43| 0| 1| 92| CZ|
| ZHTC| 657357575849| 浜珺J8890|2013-02-05 23:59:...|116.373581|39.855911| 44| 0| 1| 272| CZ|
| ZHTC| 658057524954| 浜珺Q8305|2013-02-05 23:59:...| 116.41111|39.997795| 0| 1| 1| 180| CZ|
| ZHTC| 657951524953| 浜珺P2304|2013-02-05 23:59:...|116.261139|40.016998| 0| 1| 1| 358| CZ|
| ZHTC| 658053535449| 浜珺Q4450|2013-02-05 23:59:...|116.471527|39.887917| 40| 1| 1| 0| CZ|
| ZHTC| 657951525050| 浜珺P2311|2013-02-05 23:59:...| 116.33709|39.888458| 57| 0| 1| 270| CZ|
+---------+-------------+------------+--------------------+----------+---------+-----+---------+---------+------+----+

暴力的粘过来,不想看主要看我描述吧。csv中存储这样的一系列采样点数据,每个设备在一定时间返回经纬度坐标和采样数据。

需求,查看相同设备是否两个采样点的采样间隔过长(时间过长(时间间隔),空间过长(经纬度算距离))。请问大神们有什么思路么? 刚搭的spark 一点都不会用。
...全文
1384 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
LinkSe7en 2016-11-15
  • 打赏
  • 举报
回复
引用 5 楼 houyafan 的回复:
[quote=引用 4 楼 link0007 的回复:] [quote=引用 3 楼 houyafan 的回复:] 你这个情况处理很复杂。我们之前也有类似的这个需求,搞了一个多星期。说一下我们的思路: 你首先要给记录加个流水号(自增ID)。用ZooKeeper的PERSISTENT_SEQUENTIAL类型节点。这样得到的数字是分布式自增唯一的。这个可以封装在UDF里。 打好流水号之后,就通过自JOIN得到相同SIM_ID的当前记录ID与下一条记录的ID。 把上述的表和原始的表进行JOIN,就得到当前记录的字段与下一条记录的字段,再通过我刚才说的UDF去判断就搞定了。
弄了一会儿 在数据库里可以完成这一套 在spark里面怎么实现自增ID 呢?我用的pyspark 我看居然不支持.withColumn [/quote] 百度 ZooKeeper PERSISTENT_SEQUENTIAL 把这个方法封装在udf里,在Spark SQL 的原始记录表调用,就可以得到连续且唯一的自增ID了 这是我的代码:

import org.apache.zookeeper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

/**
 * Created by Link on 2016/9/14.
 * 分布式自增id生成器
 *
 * 基于Zookeeper序列递增特性产生分布式环境下全局唯一的递增id
 */
public class DistributedIncreaseIDGen implements Watcher {
    final private static Logger log = LoggerFactory.getLogger(DistributedIncreaseIDGen.class);

    private CountDownLatch connectedSemaphore = new CountDownLatch( 1 );

    private String prefix;
    private ZooKeeper zk;

    /**
     * 构造函数
     * @param zkHosts zk节点列表
     * @param appPrefix znode前缀
     */
    public DistributedIncreaseIDGen(String zkHosts,String appPrefix) {
        prefix = appPrefix;
        for(int i = 0 ; i < 10 ; i++)
            ZookeeperUtil.pathChk(zkHosts,prefix);
        try {
            zk = new ZooKeeper(zkHosts,2000,this);
        } catch (IOException e) {
            log.error(e.getLocalizedMessage());
        }
        try {
            connectedSemaphore.await();
        } catch (InterruptedException e) {
            log.error(e.getLocalizedMessage());
        }
    }

    public String getPrefix() {
        return prefix;
    }

    public long getNextID() {
        try {
            String path = zk.create(prefix + "/id-", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);

            String paths[] = path.split("-");
            String num = paths[paths.length-1];

            long numL = Long.parseLong(num);

            zk.delete(path,-1);
            return numL;
        } catch (KeeperException | InterruptedException e) {
            log.error(e.getLocalizedMessage());
        }
        return -1;
    }

    @Override
    public void process(WatchedEvent event) {
        Event.EventType type = event.getType();
        Event.KeeperState state = event.getState();
        String path = event.getPath();

        if ( Event.KeeperState.SyncConnected == state ) {
            connectedSemaphore.countDown();
        }
    }

}
ZookeeperUtil:

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;

import java.io.IOException;

/**
 * Created by Link on 2016/9/13.
 */
public abstract class ZookeeperUtil {

    /**
     * zk路径检查,如果不存在,创建数据为空的路径
     * @param zks zk集群
     * @param path 路径
     */
    public static void pathChk(String zks,String path) {
        pathChk(zks,path,new byte[0]);
    }

    public synchronized static void pathChk(String zks,String path,byte data[]) {
        ZooKeeper zk = null;
        try {
            zk = new ZooKeeper(zks,2000, event -> {});
            String[] paths = path.split("/");
            paths = ArrayUtils.subarray(paths,1,paths.length);
            for(int i = 0 ;i < path.length() ;i++) {
                String thisPath = "/" + StringUtils.join(ArrayUtils.subarray(paths,0,i+1),"/");
                if(zk.exists(thisPath,false)==null) {
                    zk.create(thisPath,data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                }
            }
//            Stat exists = zk.exists(path, false);
//
//            if(exists==null) {
//                zk.create(path,ByteArrayUtil.toByte(0L), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
//            }
        } catch (KeeperException | InterruptedException | IOException e) {
            e.printStackTrace();
        }
    }


}
_明月 2016-11-14
  • 打赏
  • 举报
回复
抱歉,由于个人能力有限,帮不了你。
houyafan 2016-11-14
  • 打赏
  • 举报
回复
引用 4 楼 link0007 的回复:
[quote=引用 3 楼 houyafan 的回复:] 你这个情况处理很复杂。我们之前也有类似的这个需求,搞了一个多星期。说一下我们的思路: 你首先要给记录加个流水号(自增ID)。用ZooKeeper的PERSISTENT_SEQUENTIAL类型节点。这样得到的数字是分布式自增唯一的。这个可以封装在UDF里。 打好流水号之后,就通过自JOIN得到相同SIM_ID的当前记录ID与下一条记录的ID。 把上述的表和原始的表进行JOIN,就得到当前记录的字段与下一条记录的字段,再通过我刚才说的UDF去判断就搞定了。
弄了一会儿 在数据库里可以完成这一套 在spark里面怎么实现自增ID 呢?我用的pyspark 我看居然不支持.withColumn
LinkSe7en 2016-11-14
  • 打赏
  • 举报
回复
引用 3 楼 houyafan 的回复:
[quote=引用 1 楼 link0007 的回复:] 用SparkSQL。写两个UDF。第一个UDF传入两个时间,第二个传入两组坐标,根据你的逻辑判断是否过长,返回Boolean。 然后把这个当做Self Join的条件,一个left join就出来了
现在有一个问题就是,这个表里面无序的放着很多设备的采样点。不同设备的采样点没有必要判别。怎么区别是相邻的采样点。怎么区别不同设备的采样点呢?举个例子就是: +---------+-------------------+ SIM_ID | time | +---------+-------------------+ |1 | 2013-02-05 23:08 | |1 | 2013-02-05 23:09 | |2 | 2013-02-05 23:08 | |2 | 2013-02-05 23:09 | |2 | 2013-02-05 23:55 | +---------+-------------------+ 想处理成类似的下面结构 超过1分钟就是out数据 +---------+-------------------+------------+ SIM_ID | time | out | +---------+-------------------+------------+ |1 | 2013-02-05 23:08 | ? | |1 | 2013-02-05 23:09 | true | |2 | 2013-02-05 23:08 | ? | |2 | 2013-02-05 23:09 | true | |2 | 2013-02-05 23:55 | false | +---------+-------------------+------------+ 怎么把相邻的数据传入UDF?怎么判断是否不同设备? spark 是不是不能for循环呢?[/quote] 你这个情况处理很复杂。我们之前也有类似的这个需求,搞了一个多星期。说一下我们的思路: 你首先要给记录加个流水号(自增ID)。用ZooKeeper的PERSISTENT_SEQUENTIAL类型节点。这样得到的数字是分布式自增唯一的。这个可以封装在UDF里。 打好流水号之后,就通过自JOIN得到相同SIM_ID的当前记录ID与下一条记录的ID。 把上述的表和原始的表进行JOIN,就得到当前记录的字段与下一条记录的字段,再通过我刚才说的UDF去判断就搞定了。
houyafan 2016-11-14
  • 打赏
  • 举报
回复
引用 1 楼 link0007 的回复:
用SparkSQL。写两个UDF。第一个UDF传入两个时间,第二个传入两组坐标,根据你的逻辑判断是否过长,返回Boolean。 然后把这个当做Self Join的条件,一个left join就出来了
现在有一个问题就是,这个表里面无序的放着很多设备的采样点。不同设备的采样点没有必要判别。怎么区别是相邻的采样点。怎么区别不同设备的采样点呢?举个例子就是: +---------+-------------------+ SIM_ID | time | +---------+-------------------+ |1 | 2013-02-05 23:08 | |1 | 2013-02-05 23:09 | |2 | 2013-02-05 23:08 | |2 | 2013-02-05 23:09 | |2 | 2013-02-05 23:55 | +---------+-------------------+ 想处理成类似的下面结构 超过1分钟就是out数据 +---------+-------------------+------------+ SIM_ID | time | out | +---------+-------------------+------------+ |1 | 2013-02-05 23:08 | ? | |1 | 2013-02-05 23:09 | true | |2 | 2013-02-05 23:08 | ? | |2 | 2013-02-05 23:09 | true | |2 | 2013-02-05 23:55 | false | +---------+-------------------+------------+ 怎么把相邻的数据传入UDF?怎么判断是否不同设备? spark 是不是不能for循环呢?
houyafan 2016-11-14
  • 打赏
  • 举报
回复
现在有一个问题就是,这个表里面无序的放着很多设备的采样点。不同设备的采样点没有必要判别。怎么区别是相邻的采样点。怎么区别不同设备的采样点呢?举个例子就是: +---------+-------------------+ SIM_ID | time | +---------+-------------------+ |1 | 2013-02-05 23:08 | |1 | 2013-02-05 23:09 | |2 | 2013-02-05 23:08 | |2 | 2013-02-05 23:09 | |2 | 2013-02-05 23:55 | +---------+-------------------+ 想处理成类似的下面结构 超过1分钟就是out数据 +---------+-------------------+------------+ SIM_ID | time | out | +---------+-------------------+------------+ |1 | 2013-02-05 23:08 | ? | |1 | 2013-02-05 23:09 | true | |2 | 2013-02-05 23:08 | ? | |2 | 2013-02-05 23:09 | true | |2 | 2013-02-05 23:55 | false | +---------+-------------------+------------+ 怎么把相邻的数据传入UDF?怎么判断是否不同设备? spark 是不是不能for循环呢?
LinkSe7en 2016-11-14
  • 打赏
  • 举报
回复
用SparkSQL。写两个UDF。第一个UDF传入两个时间,第二个传入两组坐标,根据你的逻辑判断是否过长,返回Boolean。 然后把这个当做Self Join的条件,一个left join就出来了

1,258

社区成员

发帖
与我相关
我的任务
社区描述
Spark由Scala写成,是UC Berkeley AMP lab所开源的类Hadoop MapReduce的通用的并行计算框架,Spark基于MapReduce算法实现的分布式计算。
社区管理员
  • Spark
  • shiter
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧