如何在Spark DataFrame上应用自定义筛选功能

时间:2016-11-30 22:29:09

标签: sql scala apache-spark filter spark-dataframe

我有一个表格的DataFrame:

A_DF = |id_A: Int|concatCSV: String|

另一个:

B_DF = |id_B: Int|triplet: List[String]|

concatCSV的示例可能如下所示:

"StringD, StringB, StringF, StringE, StringZ"
"StringA, StringB, StringX, StringY, StringZ"
...

虽然triplet类似于:

("StringA", "StringF", "StringZ")
("StringB", "StringU", "StringR")
...

我想制作A_DFB_DF cartesian 集,例如;

| id_A: Int | concatCSV: String                             | id_B: Int | triplet: List[String]            |
|     14    | "StringD, StringB, StringF, StringE, StringZ" |     21    | ("StringA", "StringF", "StringZ")|
|     14    | "StringD, StringB, StringF, StringE, StringZ" |     45    | ("StringB", "StringU", "StringR")|
|     18    | "StringA, StringB, StringX, StringY, StringG" |     21    | ("StringA", "StringF", "StringZ")|
|     18    | "StringA, StringB, StringX, StringY, StringG" |     45    | ("StringB", "StringU", "StringR")|
|    ...    |                                               |           |                                  |

然后只保留StringA, StringB中出现的A_DF("concatCSV")至少有两个子串(例如B_DF("triplet"))的记录,即使用{{1}排除那些不满足条件的人。

第一个问题是:我可以在不将DF转换为RDD的情况下执行此操作吗?

第二个问题是:我可以理想地在filter步骤中完成整个事情 - 作为join条件吗?

我尝试过类似的尝试:

where

但无法解析val cartesianRDD = A_DF .join(B_DF,"right") .where($"triplet".exists($"concatCSV".contains(_))) 。我用where代替filter尝试了它,但仍然没有运气。此外,由于某些奇怪的原因,where的注释类型为cartesianRDD,而不是SchemaRDD。我是怎么做到的?最后,我在上面尝试的内容(我编写的短代码)是不完整的,因为它只保留DataFrameconcatCSVtriplet的一个子字符串的记录。

所以,第三个问题是:我应该更改为RDD并使用自定义过滤功能解决它吗?

最后,最后一个问题:我可以在DataFrames中使用自定义过滤功能吗?

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

函数CROSS JOIN已在Hive中实现,因此您可以先使用Hive SQL进行交叉联接:

A_DF.registerTempTable("a")
B_DF.registerTempTable("b")

// sqlContext should be really a HiveContext
val result = sqlContext.sql("SELECT * FROM a CROSS JOIN b") 

然后,您可以使用两个udf过滤到预期的输出。一个将您的字符串转换为单词数组,另一个为我们提供结果数组列和现有列{{1}的交集长度 }:

"triplet"