Algorithm Spark:找到至少有n个公共属性的对吗?

Algorithm Spark:找到至少有n个公共属性的对吗?,algorithm,apache-spark,apache-spark-sql,spark-streaming,spark-dataframe,Algorithm,Apache Spark,Apache Spark Sql,Spark Streaming,Spark Dataframe,我有一个数据集,由(传感器id、时间戳、数据)(传感器id是物联网设备的id,时间戳是UNIX时间,数据是当时输出的MD5散列)。表上没有主键,但每行都是唯一的 我需要找到所有对的传感器idss1和s2,这样这两个传感器至少有n(n=50)条目(时间戳,数据),它们之间有共同点,即在n不同的情况下,它们以相同的时间戳发出相同的数据 就数据量而言,我有10B行和~50M个不同的传感器ID,我相信大约有~5M对传感器ID在同一时间戳至少50次发出相同的数据 在Spark中,最好的方法是什么?我尝试了

我有一个数据集,由
(传感器id、时间戳、数据)
(传感器id是物联网设备的id,时间戳是UNIX时间,数据是当时输出的MD5散列)。表上没有主键,但每行都是唯一的

我需要找到所有对的
传感器id
s
s1
s2
,这样这两个传感器至少有
n
n=50
)条目
(时间戳,数据)
,它们之间有共同点,即在
n
不同的情况下,它们以相同的时间戳发出相同的数据

就数据量而言,我有10B行和~50M个不同的
传感器ID
,我相信大约有~5M对传感器ID在同一时间戳至少50次发出相同的数据


在Spark中,最好的方法是什么?我尝试了各种方法(按
(时间戳、数据)
分组和/或自加入),但它们的复杂性非常昂贵。

如果我的理解是正确的,那么我可以通过使用下面的简单代码来实现这一点

test(“Spark:Find至少有n个公共属性的对”){
/**
*S11210283218710,34
S11210283218730,24
S11210283218750,84
S11210283218780,54
S21210283218710,34
S21210283218730,24
S21210283218750,84
S21210283218780,54
S31210283218730,24
S31210283218750,84
S31210283218780,54
*/
val duplicateSensors=sc.textFile(“传感器数据”)
.map(line=>line.split(“,”).map(ar=>((ar(1),ar(2)),ar(0))/(ts,val),sid
.aggregateByKey(List.empty[String])(:+,:::)//分组(ts,val)(列表(n sid))
.flatmapvalue(l=>l.sorted.compositions(2))/(ts,val)(列表(2个sid组合))
.map(u._2).countByValue()//列表(s1,s3)->3,列表(s2,s3)->3,列表(s1,s2)->4(2个传感器,共有条目数)
//现在做过滤器…比50更细
复制传感器。foreach(println)
}

您将获得具有公共属性计数的对。

这是一个伪代码,从Spark中提取。您可以先对数据集进行排序:

select id, timestamp, data order by timestamp, data, id
示例性10行:

s1,100,a  #1
s2,100,a  #2
s3,100,a  #3
s4,100,b  #4
s1,101,a  #5
s3,101,b  #6
s4,101,b  #7
s2,101,a  #8
s3,102,b  #9
s4,102,b  #10
现在从上到下迭代,只要时间戳和数据与前面的条目相同,就构建条目列表

在我们的示例中,行1-3形成了这样一个列表,因此我们已经看到了一些潜在的对:

s1, s2
s1, s3
s2, s3
第4行只是一个带有(100,b)的条目,我们可以跳过它。 第5行只有一个带有(101,a)的条目,我们可以跳过它

第6行和第7行是新的一对:

s3, s4
9号和10号也是一对

把所有这些放在一起,就可以很容易地数到几对:

s1, s2
s1, s3
s2, s3
s3, s4
s3, s4
这种方法的好处是,如果可以对文件进行排序,则可以将已排序的数据集拆分为多个较小的数据块(数据块应在组边界上拆分,即#1、2、3应在一个数据块中),计算数据对,并将最终结果作为最后一步合并

我希望这能有所帮助。

以下是我的做法

首先,生成一些虚假数据:

#/usr/bin/env蟒蛇3
随机输入
fout=打开('test_data.csv','w'))
i=0
对于范围内的x(100000):
如果i>=1000000:
打破
对于范围内的y(random.randint(0100)):
i=i+1
时间戳=x
传感器id=random.randint(0,50)
数据=random.randint(01000)
写入(“{}{}{}\n.”格式(时间戳、传感器id、数据))
现在,您可以按如下方式处理数据

如果让行数为N,唯一时间戳数为T,每个时间戳的预期传感器数为T,则每个操作的复杂性如注释所示

导入itertools
#将一个集合转换为集合中所有唯一无序对的列表,不带
#包括自配对
def对(x):
温度=[]
x=列表(x)
对于范围内的i(len(x)):
对于范围(i+1,len(x))内的j:
临时附加((x[i],x[j]))
返回温度
#加载数据
#O(N)加载数据的时间
fin=sc.textFile(“file:///z/test_data.csv")
#按空格分割数据,仅保留时间戳和传感器ID部分
#O(N)分割每行数据的时间
lines=fin.map(lambda行:line.split(“”[0:2]))
#将每行转换为时间戳集对,其中时间戳集包含传感器
#O(N)使每行成为时间戳哈希集对的时间
monosets=lines.map(lambda行:(行[0],集(行[1]))
#按时间戳组合集合,以生成时间戳和所有传感器的列表
#每个时间戳
#O(TS)将每行放入大小为O(T)的哈希表的时间,其中每行
#哈希表中的条目是一个哈希集
时间组=集合。还原基(λa,b:a | b)
#将每个时间戳处的集合转换为所选传感器的所有对的列表
#该时间戳上的数据
#O(ts^2)为每个时间戳执行所有对的时间
shared=timegroups.flatMap(lambda-tg:PairsWithoutSelf(tg[1]))
#将每个传感器对与一个值关联
#O(ts^2)时间
monoshared=shared.map(λx:(x,1))
#按传感器对求和
#O(ts^2)时间
paircounts=monoshard.reduceByKey(λa,b:a+b)
#高击球员筛选
#O(5)
#显示结果
好的,伯爵

时间复杂度有点不稳定,因为我在做这个答案有点晚,但瓶颈至少应该是可见的。

请添加一些示例数据、尝试的代码和预期的输出。这对我提到的数据集的大小不起作用。特别是这个O(s^2),其中s是传感器的数量。@m69,我很抱歉。我是新来的。删除图像。添加了代码片段。谢谢@理查德,修好了。谢谢,@RBanerjee!