Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用作为字符串数组的行字段筛选spark数据帧_Scala_Apache Spark - Fatal编程技术网

Scala 使用作为字符串数组的行字段筛选spark数据帧

Scala 使用作为字符串数组的行字段筛选spark数据帧,scala,apache-spark,Scala,Apache Spark,使用Spark 1.5和Scala 2.10.6 我试图通过一个字符串数组字段“tags”来过滤数据帧。正在查找标记为“private”的所有行 val report = df.select("*") .where(df("tags").contains("private")) 获取: 线程“main”org.apache.spark.sql.AnalysisException中的异常: 由于数据类型不匹配,无法解析“Contains(tags,private)”: 参数1需要字符串类型,

使用Spark 1.5和Scala 2.10.6

我试图通过一个字符串数组字段“tags”来过滤数据帧。正在查找标记为“private”的所有行

val report = df.select("*")
  .where(df("tags").contains("private"))
获取:

线程“main”org.apache.spark.sql.AnalysisException中的异常: 由于数据类型不匹配,无法解析“Contains(tags,private)”: 参数1需要字符串类型,但“tags”是数组类型 类型

过滤法更合适吗

更新:

数据来自cassandra adapter,但一个最简单的示例显示了我正在尝试做什么,并且也得到了上述错误:

  def testData (sc: SparkContext): DataFrame = {
    val stringRDD = sc.parallelize(Seq("""
      { "name": "ed",
        "tags": ["red", "private"]
      }""",
      """{ "name": "fred",
        "tags": ["public", "blue"]
      }""")
    )
    val sqlContext = new org.apache.spark.sql.SQLContext(sc)
    import sqlContext.implicits._
    sqlContext.read.json(stringRDD)
  }
  def run(sc: SparkContext) {
    val df1 = testData(sc)
    df1.show()
    val report = df1.select("*")
      .where(df1("tags").contains("private"))
    report.show()
  }
更新:标记数组可以是任意长度,“private”标记可以位于任意位置

更新:一个有效的解决方案:UDF

val filterPriv = udf {(tags: mutable.WrappedArray[String]) => tags.contains("private")}
val report = df1.filter(filterPriv(df1("tags")))

您可以使用ordinal来引用json数组的,例如在您的示例中
df(“标记”)(0)
。这是一个工作样本

scala> val stringRDD = sc.parallelize(Seq("""
     |       { "name": "ed",
     |         "tags": ["private"]
     |       }""",
     |       """{ "name": "fred",
     |         "tags": ["public"]
     |       }""")
     |     )
stringRDD: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[87] at parallelize at <console>:22

scala> import sqlContext.implicits._
import sqlContext.implicits._

scala> sqlContext.read.json(stringRDD)
res28: org.apache.spark.sql.DataFrame = [name: string, tags: array<string>]

scala> val df=sqlContext.read.json(stringRDD)
df: org.apache.spark.sql.DataFrame = [name: string, tags: array<string>]

scala> df.columns
res29: Array[String] = Array(name, tags)

scala> df.dtypes
res30: Array[(String, String)] = Array((name,StringType), (tags,ArrayType(StringType,true)))

scala> val report = df.select("*").where(df("tags")(0).contains("private"))
report: org.apache.spark.sql.DataFrame = [name: string, tags: array<string>]

scala> report.show
+----+-------------+
|name|         tags|
+----+-------------+
|  ed|List(private)|
+----+-------------+
scala>val stringRDD=sc.parallelize(Seq(“”)
|{“姓名”:“ed”,
|“标签”:[“专用”]
|       }""",
|“{”姓名“:“弗雷德”,
|“标签”:[“公共”]
|       }""")
|     )
stringRDD:org.apache.spark.rdd.rdd[String]=ParallelCollectionRDD[87]位于parallelize at:22
scala>导入sqlContext.implicits_
导入sqlContext.implicits_
scala>sqlContext.read.json(stringRDD)
res28:org.apache.spark.sql.DataFrame=[名称:字符串,标记:数组]
scala>val df=sqlContext.read.json(stringRDD)
df:org.apache.spark.sql.DataFrame=[名称:字符串,标记:数组]
scala>df.columns
res29:Array[String]=数组(名称、标记)
scala>df.dtypes
res30:Array[(String,String)]=数组((名称,StringType),(标记,ArrayType(StringType,true)))
scala>val report=df.select(“*”)。其中(df(“tags”)(0)。包含(“private”))
报告:org.apache.spark.sql.DataFrame=[名称:字符串,标记:数组]
scala>report.show
+----+-------------+
|名称|标签|
+----+-------------+
|教育署名单(私人)|
+----+-------------+

我认为如果您使用
where(array_contains(…))
它会起作用。以下是我的结果:

scala> import org.apache.spark.SparkContext
import org.apache.spark.SparkContext

scala> import org.apache.spark.sql.DataFrame
import org.apache.spark.sql.DataFrame

scala> def testData (sc: SparkContext): DataFrame = {
     |     val stringRDD = sc.parallelize(Seq
     |      ("""{ "name": "ned", "tags": ["blue", "big", "private"] }""",
     |       """{ "name": "albert", "tags": ["private", "lumpy"] }""",
     |       """{ "name": "zed", "tags": ["big", "private", "square"] }""",
     |       """{ "name": "jed", "tags": ["green", "small", "round"] }""",
     |       """{ "name": "ed", "tags": ["red", "private"] }""",
     |       """{ "name": "fred", "tags": ["public", "blue"] }"""))
     |     val sqlContext = new org.apache.spark.sql.SQLContext(sc)
     |     import sqlContext.implicits._
     |     sqlContext.read.json(stringRDD)
     |   }
testData: (sc: org.apache.spark.SparkContext)org.apache.spark.sql.DataFrame

scala>   
     | val df = testData (sc)
df: org.apache.spark.sql.DataFrame = [name: string, tags: array<string>]

scala> val report = df.select ("*").where (array_contains (df("tags"), "private"))
report: org.apache.spark.sql.DataFrame = [name: string, tags: array<string>]

scala> report.show
+------+--------------------+
|  name|                tags|
+------+--------------------+
|   ned|[blue, big, private]|
|albert|    [private, lumpy]|
|   zed|[big, private, sq...|
|    ed|      [red, private]|
+------+--------------------+
scala>import org.apache.spark.SparkContext
导入org.apache.spark.SparkContext
scala>import org.apache.spark.sql.DataFrame
导入org.apache.spark.sql.DataFrame
scala>DefTestData(sc:SparkContext):数据帧={
|val stringRDD=sc.parallelize(顺序
|(“{”name:“ned”,“tags:[“blue”,“big”,“private”]}”“,
|“{”name:“albert”,“tags:[“private”,“lumpy”]}”“,
|“{”name:“zed”,“tags:[“big”,“private”,“square”]}”“,
|“{”name:“jed”,“tags:[“green”,“small”,“round”]}”“,
|“{”name:“ed”,“tags:[“red”,“private”]}”“,
|“{”name:“fred”,“tags:[“public”,“blue”]}”“)
|val sqlContext=new org.apache.spark.sql.sqlContext(sc)
|导入sqlContext.implicits_
|sqlContext.read.json(stringRDD)
|   }
testData:(sc:org.apache.spark.SparkContext)org.apache.spark.sql.DataFrame
斯卡拉>
|val df=测试数据(sc)
df:org.apache.spark.sql.DataFrame=[名称:字符串,标记:数组]
scala>val report=df.select(“*”)。其中(数组_包含(df(“标记”),“private”))
报告:org.apache.spark.sql.DataFrame=[名称:字符串,标记:数组]
scala>report.show
+------+--------------------+
|名称|标签|
+------+--------------------+
|ned |[蓝色,大,私人]|
|阿尔伯特|[私人,笨重]|
|zed |[大的,私人的,方形的]|
|ed |[红色,私人]|
+------+--------------------+

请注意,如果您编写
where(array_包含(df(“tags”),“private”)
,但如果您编写
where(df(“tags”)。array_包含(“private”)
(更直接地类似于您最初编写的内容)它失败于
数组\u contains不是org.apache.spark.sql.Column
的成员。查看
Column
的源代码,我发现有一些东西需要处理
contains
(为此构建
contains
实例)但不是
array\u contains
。这可能是一个疏忽。

发布数据示例以及创建dfOne选项的方法是构建一个UDF。好吧,在查看源代码之后(因为
列的scaladoc.contains
只说“包含其他元素”,这不是很有启发性),我看到
Column.contains
构造了
org.apache.spark.sql.catalyst.expressions.contains的一个实例,该实例表示“如果字符串
left
包含字符串
right
,则返回true的函数”。因此似乎
df1(“标记”).contains
在这种情况下不能执行我们希望它执行的操作。我不知道建议使用什么替代方法。在
中也有
数组contains
…expressions
但是
似乎没有使用它。事实上,在将数据更改为字符串而不是字符串数组后,我发现查询成功。@DavidMaust,我有一个UDF来工作:
val filterPriv=UDF{(tags:mutable.WrappedArray[String])=>tags.contains(“private”)};val report=df1.filter(filterPriv(df1(“tags”))
仍在寻找更好的东西,但至少我没有被阻止。thx!谢谢。如果pos是固定的,那么它可以工作,但它不是。我应该让测试数据更复杂一点,数组中可以有任意数量的标记,位置是任意的。@navicore那么你的代码应该可以工作。检查我的updateinteresting,我遗漏了一些东西,看起来像实际上,我正在做什么,但得到了错误。现在仔细检查spark版本…@navicore这是在1.5.4thx上。我一定是在什么地方交叉了手。我尝试了1.5.1和1.6并且
val report=df.select(“*”)。其中(df(“tags”).contains(“private”)
在orig post中给了我那个错误。挖掘…
。选择(“*”)
不需要=>
df.where(…)…
在使用此方法之前,需要
导入org.apache.spark.sql.functions.array\u包含的内容。