Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.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_Dataframe_Apache Spark Sql - Fatal编程技术网

Scala 如何检测Spark数据帧是否有列

Scala 如何检测Spark数据帧是否有列,scala,apache-spark,dataframe,apache-spark-sql,Scala,Apache Spark,Dataframe,Apache Spark Sql,当我从Spark SQL中的JSON文件创建数据帧时,如何在调用之前判断给定列是否存在 JSON模式示例: { "a": { "b": 1, "c": 2 } } 这就是我想做的: 电位_列=序号b、c、d df=sqlContext.read.jsonfilename potential_columns.mapcolumn=>ifdf.hasColumncolumn df.selectsa.$column 但是我找不到hasColumn的好函数。我得到的最接近的结果是

当我从Spark SQL中的JSON文件创建数据帧时,如何在调用之前判断给定列是否存在

JSON模式示例:

{
  "a": {
    "b": 1,
    "c": 2
  }
}
这就是我想做的:

电位_列=序号b、c、d df=sqlContext.read.jsonfilename potential_columns.mapcolumn=>ifdf.hasColumncolumn df.selectsa.$column 但是我找不到hasColumn的好函数。我得到的最接近的结果是测试列是否在这个有点笨拙的数组中:

scala> df.select("a.*").columns
res17: Array[String] = Array(b, c)

实际上,为了使用列,甚至不需要调用select,只需在数据帧本身上调用它即可

// define test data
case class Test(a: Int, b: Int)
val testList = List(Test(1,2), Test(3,4))
val testDF = sqlContext.createDataFrame(testList)

// define the hasColumn function
def hasColumn(df: org.apache.spark.sql.DataFrame, colName: String) = df.columns.contains(colName)

// then you can just use it on the DF with a given column name
hasColumn(testDF, "a")  // <-- true
hasColumn(testDF, "c")  // <-- false
然后您可以将其用作:

testDF.hasColumn("a") // <-- true
testDF.hasColumn("c") // <-- false

您的另一个选择是对df.columns和您的潜在_列执行一些数组操作,在这种情况下是一个交集

唉,这对上面的内部对象场景不起作用。您需要查看该模式

我要将您的潜在_列更改为完全限定的列名

val potential_columns = Seq("a.b", "a.c", "a.d")

// Our object model
case class Document( a: String, b: String, c: String)
case class Document2( a: Document, b: String, c: String)

// And some data...
val df = sc.parallelize(Seq(Document2(Document("a", "b", "c"), "c2")), 2).toDF

// We go through each of the fields in the schema.
// For StructTypes we return an array of parentName.fieldName
// For everything else we return an array containing just the field name
// We then flatten the complete list of field names
// Then we intersect that with our potential_columns leaving us just a list of column we want
// we turn the array of strings into column objects
// Finally turn the result into a vararg (: _*)
df.select(df.schema.map(a => a.dataType match { case s : org.apache.spark.sql.types.StructType => s.fieldNames.map(x => a.name + "." + x) case _ => Array(a.name) }).flatMap(x => x).intersect(potential_columns).map(df(_)) : _*).show

这只会深入一个层次,所以要使其通用化,您需要做更多的工作。

只要假设它存在,并让它通过Try失败即可。简单明了,支持任意嵌套:

import scala.util.Try
import org.apache.spark.sql.DataFrame

def hasColumn(df: DataFrame, path: String) = Try(df(path)).isSuccess

val df = sqlContext.read.json(sc.parallelize(
  """{"foo": [{"bar": {"foobar": 3}}]}""" :: Nil))

hasColumn(df, "foobar")
// Boolean = false

hasColumn(df, "foo")
// Boolean = true

hasColumn(df, "foo.bar")
// Boolean = true

hasColumn(df, "foo.bar.foobar")
// Boolean = true

hasColumn(df, "foo.bar.foobaz")
// Boolean = false
或者更简单:

val columns = Seq(
  "foobar", "foo", "foo.bar", "foo.bar.foobar", "foo.bar.foobaz")

columns.flatMap(c => Try(df(c)).toOption)
// Seq[org.apache.spark.sql.Column] = List(
//   foo, foo.bar AS bar#12, foo.bar.foobar AS foobar#13)
Python等价物:

从pyspark.sql.utils导入AnalysisException 从pyspark.sql导入行 def具有_柱DF,柱: 尝试: df[col] 返回真值 例外情况除外: 返回错误 df=sc.parallelize[Rowfoo=[Rowbar=Rowfoobar=3]].toDF 我有一个朋友,福巴 错误的 你有吗,福 符合事实的 我有一个专栏,foo.bar 符合事实的 有四列,foo.bar.foobar 符合事实的 有四个栏df,foo.bar.foobaz 错误的 Try不是最优的,因为它会在做出决定之前计算Try中的表达式

对于大型数据集,请在Scala中使用以下命令:


我通常使用的另一个选项是

df.columns.contains("column-name-to-check")
这将返回一个布尔值

def hasColumn(df: org.apache.spark.sql.DataFrame, colName: String) =
  Try(df.select(colName)).isSuccess

使用上述函数检查是否存在包含嵌套列名的列。

对于那些无意中发现此问题并寻找Python解决方案的人,我使用:

if 'column_name_to_check' in df.columns:
    # do something

当我使用Python尝试@Jai Prakash对df.columns.contains的回答“column-name-to-check”时,我得到了AttributeError:“list”对象没有“contains”属性。

如果在加载json时使用模式定义分解json,则无需检查该列。如果它不在json源代码中,它将显示为空列

        val schemaJson = """
  {
      "type": "struct",
      "fields": [
          {
            "name": field1
            "type": "string",
            "nullable": true,
            "metadata": {}
          },
          {
            "name": field2
            "type": "string",
            "nullable": true,
            "metadata": {}
          }
      ]
  }
        """
    val schema = DataType.fromJson(schemaJson).asInstanceOf[StructType]

    val djson = sqlContext.read
    .schema(schema )
    .option("badRecordsPath", readExceptionPath)
    .json(dataPath)

在PySpark中,df.columns提供数据帧中的列列表,因此 df.columns中的colName
将返回一个True或False。试穿一下。祝你好运

对于嵌套列,可以使用

df.schema.simpleString().find('column_name')

在pyspark中,您可以简单地运行

df列中的“字段”


这不适用于嵌套列。从json{a:{b:1,c:0}来看,这也适用于结构化字段。使用contains函数的解决方案没有+1乍一看,dfpath或df[col]看起来是一个非常昂贵的测试,但这都是懒惰的dag建筑,所以它很便宜,对吗?@Davos,这与懒惰没有什么关系。列不是数据容器,而是查询描述模型的组件。在更广泛的上下文中,若要了解有关数据集的任何信息,请处理并检查其逻辑QueryExecution.Analysized plan,这适用于col/同时应用resolve或schema/列。@10465355SaysRestoreTemonica谢谢,这正是我的意思。我指的不是Scala中的惰性指令,而是Spark如何创建逻辑计划、将其转换为物理计划,然后在集群上执行任务的分阶段方法。如果在逻辑计划阶段解决了这个问题,那么它是便宜的。是的,这是正确的,它不适用于嵌套列。我同意Try不是最佳选择。我要做的是:我用字段数组创建一列,然后用数组进行测试,数组包含:val fields=df.schema.fieldNames;df.withColumnfields,litfields.withColumnhas_column,当narray_包含$fields,field1,littrue``这种检查数据帧中的列的方法会减慢spark处理吗?@Vassista你能帮我更好地理解你的问题吗?是否有其他方法可以比较性能?df1.columns显示['bankData','reference','submissionTime'];但是df1['bankData']['userAddress'].列显示列,不显示结构,我是否缺少什么?
if 'column_name_to_check' in df.columns:
    # do something
        val schemaJson = """
  {
      "type": "struct",
      "fields": [
          {
            "name": field1
            "type": "string",
            "nullable": true,
            "metadata": {}
          },
          {
            "name": field2
            "type": "string",
            "nullable": true,
            "metadata": {}
          }
      ]
  }
        """
    val schema = DataType.fromJson(schemaJson).asInstanceOf[StructType]

    val djson = sqlContext.read
    .schema(schema )
    .option("badRecordsPath", readExceptionPath)
    .json(dataPath)
df.schema.simpleString().find('column_name')