我有一个包含csv
列的大型id,time,location
文件。我将它设为RDD,并且想要计算trips
的一些聚合度量,当旅程被定义为相同id的时间连续记录集时,在任一侧至少相隔1小时。我是新来的火花。 (related)
为此,我想创建一个包含(trip_id,(time, location))
形式元素的RDD,并使用reduceByKey
来计算所有需要的指标。
为了计算trip_id
,我尝试实现链接问题的SQL方法,制作一个指标字段,记录该记录是否为旅行的开始,并对该指标字段进行累计求和。这听起来不像分布式方法:有更好的方法吗?
此外,如何添加此指标字段?如果与同一id
的前一记录的时差超过一小时,则它应为1,否则为0。我首先想到groupBy
id,然后对每个值进行排序,但它们将在一个数组中,因此不适合sortByKey
,并且没有lead
函数在SQL中获取以前的值。
示例:对于RDD
(1,9:30,50)
(1,9:37,70)
(1,9:50,80)
(2,19:30,10)
(1,20:50,20)
我们希望首先将其转换为具有时差的RDD,
(1,9:30,50,inf)
(1,9:37,70,00:07:00)
(1,9:50,80,00:13:00)
(2,19:30,10,inf)
(2,20:50,20,01:20:00)
(最早的记录的值是scala' s PositiveInfinity
常数)
并将此最后一个字段转换为指示字段,该字段是否大于1,表示我们是否开始旅行,
(1,9:30,50,1)
(1,9:37,70,0)
(1,9:50,80,0)
(2,19:30,10,1)
(2,20:50,20,1)
然后将其转换为trip_id
(1,9:30,50,1)
(1,9:37,70,1)
(1,9:50,80,1)
(2,19:30,10,2)
(2,20:50,20,3)
然后使用此trip_id
作为聚合的关键。
预处理只是加载文件并删除标题
val rawdata=sc.textFile("some_path")
def isHeader(line:String)=line.contains("id")
val data=rawdata.filter(!isHeader(_))
修改
在尝试使用spark SQL时,我遇到了有关时差的错误:
val lags=sqlContext.sql("
select time - lag(time) over (partition by id order by time) as diff_time from data
");
因为spark不知道如何区分两个时间戳。我试图检查这个差异是否超过1小时。
它也没有识别我在网上找到的函数getTime
作为答案,以下也返回错误(Couldn't find window function time.getTime
):
val lags=sqlContext.sql("
select time.getTime() - (lag(time)).getTime() over (partition by id order by time)
from data
");
即使为数字属性创建类似的lag
差异,也可以使用
val lag_numeric=sqlContext.sql("
select longitude - lag(longitude) over (partition by id order by time)
from data"); //works
Spark也没有认识到函数Hours.hoursBetween
。我正在使用spark 1.4.0
。
我还试图定义一个合适的用户定义函数,但奇怪的是在查询中无法识别UDFS:
val timestamp_diff: ((Timestamp,Timestamp) => Double) =
(d1: Timestamp,d2: Timestamp) => d1.getTime()-d2.getTime()
val lags=sqlContext.sql("select timestamp_diff(time,lag(time))
over (partition by id order by time) from data");
那么,如何激发测试时间戳之间的差异是否超过一小时?
完整代码:
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.functions._
import sqlContext._
val sqlContext = new org.apache.spark.sql.hive.HiveContext(sc)
import sqlContext.implicits._
import org.apache.spark.sql.hive.HiveContext//For window functions
import java.util.Date
import java.sql.Timestamp
case class Record(id: Int, time:Timestamp, longitude: Double, latitude: Double)
val raw_data=sc.textFile("file:///home/sygale/merged_table.csv")
val data_records=
raw_data.map(line=>
Record( line.split(',')(0).toInt,
Timestamp.valueOf(line.split(',')(1)),
line.split(',')(2).toDouble,
line.split(',')(3).toDouble
))
val data=data_records.toDF()
data.registerTempTable("data")
val lags=sqlContext.sql("
select time - lag(time) over (partition by id order by time) as diff_time from data
");