Pyspark:groupby然后计算真值

时间:2016-06-24 00:14:13

标签: apache-spark pyspark

我的数据结构是JSON格式:

"header"{"studentId":"1234","time":"2016-06-23","homeworkSubmitted":True}
"header"{"studentId":"1234","time":"2016-06-24","homeworkSubmitted":True}
"header"{"studentId":"1234","time":"2016-06-25","homeworkSubmitted":True}
"header"{"studentId":"1236","time":"2016-06-23","homeworkSubmitted":False}
"header"{"studentId":"1236","time":"2016-06-24","homeworkSubmitted":True}
....

我需要绘制一个直方图,显示家庭作业的数量已提交:对所有stidentIds为真。我编写的代码使数据结构变得扁平化,因此我的密钥是header.studentId,header.time和header.homeworkSubmitted。

我使用keyBy按studentId分组:

    initialRDD.keyBy(lambda row: row['header.studentId'])
              .map(lambda (k,v): (k,v['header.homeworkSubmitted']))
              .map(mapTF).groupByKey().mapValues(lambda x: Counter(x)).collect()

这给了我这样的结果:

("1234", Counter({0:0, 1:3}),
("1236", Counter(0:1, 1:1))

我只需要1的计数,可能映射到列表,这样我就可以使用matplotlib绘制直方图。我不知道如何继续并过滤所有内容。

编辑:最后我遍历字典并将计数添加到列表中,然后绘制列表的直方图。我想知道是否有一种更优雅的方式来完成我在代码中概述的整个过程。

3 个答案:

答案 0 :(得分:8)

df = sqlContext.read.json('/path/to/your/dataset/')
df.filter(df.homeworkSubmitted == True).groupby(df.studentId).count()

如果有"header"True而不是true

,请注意它无效JSON

答案 1 :(得分:1)

我现在没有Spark在我面前,虽然我可以在明天编辑这个。

但是,如果我理解这一点,你有三个键值RDD,需要按homeworkSubmitted = True过滤。我想你会把它变成一个数据帧,然后使用:

def approxTime(x, y):
     if int(y) <= 24:
         print("the time is about quarter past" + str(y))
     elif 25 >= int(y) <=40:
         print("the time is about half past" + str(y))
     elif 41 >= int(y) <= 54:
         print("the time is about quarter past" + str(y+1))
     else:
         print("the time is about" + str(y+1) +"o'clock")
approxTime(3, 18)

如果您想根据其他列浏览子集,则可以使用group by operations。

答案 2 :(得分:0)

您可以过滤掉false,将其保存在RDD中,然后使用计数器

计算True
initialRDD.filter(lambda row : row['header.homeworkSubmitted'])

另一个解决方案是对布尔值求和

data = sc.parallelize([('id1',True),('id1',True),
                    ('id2',False),
                    ('id2',False),('id3',False),('id3',True) ])


data.reduceByKey(lambda x,y:x+y).collect()

输出

[('id2', 0), ('id3', 1), ('id1', 2)]