如何在spark scala中使用带有2列的array_contains?

时间:2018-01-25 08:03:06

标签: scala apache-spark dataframe

我有一个问题,我想检查一个字符串数组是否包含另一列中的字符串。我目前正在使用下面的代码,这是一个错误。

.withColumn("is_designer_present", when(array_contains(col("list_of_designers"),$"dept_resp"),1).otherwise(0))

错误:

java.lang.RuntimeException: Unsupported literal type class org.apache.spark.sql.ColumnName dept_resp
  at org.apache.spark.sql.catalyst.expressions.Literal$.apply(literals.scala:77)

4 个答案:

答案 0 :(得分:3)

您可以编写udf函数来完成工作

import org.apache.spark.sql.functions._
def stringContains = udf((array: collection.mutable.WrappedArray[String], str: String) => array.contains(str))
df.withColumn("is_designer_present", when(stringContains(col("list_of_designers"), $"dept_resp"),1).otherwise(0))

您可以从udf函数本身返回适当的值,这样您就不必使用when函数

import org.apache.spark.sql.functions._
def stringContains = udf((array: collection.mutable.WrappedArray[String], str: String) => if (array.contains(str)) 1 else 0)
df.withColumn("is_designer_present", stringContains(col("list_of_designers"), $"dept_resp"))

答案 1 :(得分:2)

使用Spark 1.6,您可以将array_contains()作为字符串包装到expr()函数中:

import org.apache.spark.sql.functions.expr

.withColumn("is_designer_present",
    when(expr("array_contains(list_of_designers, dept_resp)"), 1).otherwise(0))

array_contains中的expr形式可以接受列作为第二个参数。

答案 2 :(得分:0)

你可以使用explode在没有UDF的情况下完成。

<html lang="en">
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
		<p></p>
		<button class="btn btn-outline-primary" data-toggle="modal" data-target="#insertData">Insert Data</button>
				<!-- Modal -->
		<div class="modal fade" id="insertData" tabindex="-1" role="dialog" aria-labelledby="insertLabel" aria-hidden="true">
		  <div class="modal-dialog" role="document">
		    <div class="modal-content">
		      <div class="modal-header">
		        <h5 class="modal-title" id="insertLabel">Insert Data</h5>
		        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
		          <span aria-hidden="true">&times;</span>
		        </button>
		      </div>
		      <form>
		      <div class="modal-body">
		       <form>
				  <div class="form-group">
				    <label for="nm">Full Name</label>
				    <input type="email" class="form-control" id="nm" aria-describedby="emailHelp" placeholder="Full Name">
				  </div>
				  <div class="form-group">
				    <label for="em">Email</label>
				    <input type="password" class="form-control" id="em" placeholder="Email">
				  </div>
				</form>
		      </div>
		      <div class="modal-footer">
		        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
		        <button type="submit" onclick="saveData()" class="btn btn-primary">Save</button>
		      </div>
		      </form>
		    </div>
		  </div>
		</div>
		<p></p>
	</div>

</body>
</html>

然后你去,如果结果&gt; 0然后&#34; dept_rest&#34;包含值。

答案 3 :(得分:0)

我知道这是一个有点老的问题,但我发现自己陷入了类似的困境,并找到了以下解决方案。它使用 Spark 原生函数(因此它不会受到与 UDF 相关的性能回归的影响,并且它不依赖于字符串表达式(难以维护)。

def array_contains_column(arrayColumn: Column, valueColumn: Column): Column = {
    new Column(ArrayContains(arrayColumn.expr, valueColumn.expr))
}

// ...

df.withColumn(
    "is_designer_present",
    when(
        array_contains_column(col("list_of_designers"),col("dept_resp")),
        1
    ).otherwise(0)
)