Spark DataFrame中的列(结构类型)的掩码字段

时间:2017-05-11 17:27:19

标签: xml scala apache-spark dataframe masking

我从XML文件创建了一个DataFrame。创建的DataFrame具有以下方案。

val df = hiveContext.read.format("com.databricks.spark.xml").option("rowTag", row_tag_name).load(data_dir_path_xml)

df.printSchema()

            root
             |-- samples: struct (nullable = true)
             |    |-- sample: array (nullable = true)
             |    |    |-- element: struct (containsNull = true)
             |    |    |    |-- abc: string (nullable = true)
             |    |    |    |-- def: long (nullable = true)
             |    |    |    |-- type: string (nullable = true)
             |-- abc: string (nullable = true)

我想屏蔽数据帧中的abc / def。

我能够到达我想要的领域:

val abc = df.select($"samples.sample".getField("abc"))

但我想在数据帧df中屏蔽字段abc / def(用XXXX替换abc字段)。请帮帮我

2 个答案:

答案 0 :(得分:0)

databricks xml库中似乎没有太多(如果有的话)支持来操作基于XML的数据帧的内容(能否使用XSLT会不会很酷?! )。但是你总是可以直接操纵推断的行,例如

val abc = df.map(row => {
  val samples = row.getStruct(0).getSeq(0)
  val maskedSamples = samples.map(sample => {
     Row("xxxxx", sample.getLong(1), sample.getString(2))
  }
  Row(Row(maskedSamples), row.getString(1))
}

上面的代码可能与您想要的转换不完全匹配,因为它有点不清楚,但您明白了。

答案 1 :(得分:0)

我建议您将samples array structType拆分为columnsStructFields),以便您可以根据需要屏蔽/替换它们。如果您愿意,也可以稍后申请dataframe functions 下面是分成三列的代码

df.withColumn("abcd", lit($"samples.sample.abc"))
      .withColumn("def", lit($"samples.sample.def"))
      .withColumn("type", lit($"samples.sample.type"))

如果需要,您可以删除samples column

.drop("samples")

由于您要使用XXXX屏蔽abcdef,您可以

df.withColumn("abcd", lit("XXXX"))
      .withColumn("def", lit("XXXX"))
      .withColumn("type", lit($"samples.sample.type"))
      .drop("samples")

注意:abcd column name被使用,因为您的架构中已有另一个column abc

编辑以满足以下@Raj评论:

如果要保留original schema并且不需要单独columns,那么创建case classudf函数应该可以解决问题

def mask = udf((typ: mutable.WrappedArray[String]) => Raj("XXXXX", Option(0L), typ(0)))
需要Case class

Raj

case class Raj(abc : String,
               dfe : Option[Long],
               typ: String)

最后在udf

中传递type来调用withColumn函数
df.withColumn("samples", struct(array(mask(col("samples.sample.type"))) as "sample"))

这应该可以获得工作输出