如何使用Spark 2掩盖列



我有一些表,其中我需要掩盖其一些列。要掩盖的列因表而异,我正在从application.conf文件中读取这些列。

例如,对于员工表,如下所示

+----+------+-----+---------+
| id | name | age | address |
+----+------+-----+---------+
| 1  | abcd | 21  | India   |
+----+------+-----+---------+
| 2  | qazx | 42  | Germany |
+----+------+-----+---------+

如果我们想掩盖名称和年龄列,则我以序列获得这些列。

val mask = Seq("name", "age")

掩盖后的预期值是:

+----+----------------+----------------+---------+
| id | name           | age            | address |
+----+----------------+----------------+---------+
| 1  | *** Masked *** | *** Masked *** | India   |
+----+----------------+----------------+---------+
| 2  | *** Masked *** | *** Masked *** | Germany |
+----+----------------+----------------+---------+

如果我的员工表有数据框架,那么掩盖这些列的方法是什么?

如果我有payment表,如下所示,并且想要掩盖namesalary列,则我将sequence的掩码列作为

+----+------+--------+----------+
| id | name | salary | tax_code |
+----+------+--------+----------+
| 1  | abcd | 12345  | KT10     |
+----+------+--------+----------+
| 2  | qazx | 98765  | AD12d    |
+----+------+--------+----------+
val mask = Seq("name", "salary")

我尝试了类似这样的mask.foreach(c => base.withColumn(c, regexp_replace(col(c), "^.*?$", "*** Masked ***" ) ) ),但没有返回任何内容。


感谢@philantrovert,我找到了解决方案。这是我使用的解决方案:

def maskData(base: DataFrame, maskColumns: Seq[String]) = {
    val maskExpr = base.columns.map { col => if(maskColumns.contains(col)) s"'*** Masked ***' as ${col}" else col }
    base.selectExpr(maskExpr: _*)
}

最简单,最快的方法是使用 withColumn,然后用 "*** Masked ***"覆盖列中的值。使用您的小示例dataframe

val df = spark.sparkContext.parallelize( Seq (
  (1, "abcd", 12345, "KT10" ),
  (2, "qazx", 98765, "AD12d")
)).toDF("id", "name", "salary", "tax_code")

如果您有少量的列要掩盖,并带有已知名称,那么您可以简单地做:

val mask = Seq("name", "salary")
df.withColumn("name", lit("*** Masked ***"))
  .withColumn("salary", lit("*** Masked ***"))

否则,您需要创建一个循环:

var df2 = df
for (col <- mask){
  df2 = df2.withColumn(col, lit("*** Masked ***"))
}

这两种方法都将为您带来这样的结果:

+---+--------------+--------------+--------+
| id|          name|        salary|tax_code|
+---+--------------+--------------+--------+
|  1|*** Masked ***|*** Masked ***|    KT10|
|  2|*** Masked ***|*** Masked ***|   AD12d|
+---+--------------+--------------+--------+

请检查下面的代码。关键是udf函数。

val df = ss.sparkContext.parallelize( Seq (
  ("c1", "JAN-2017", 49 ),
  ("c1", "MAR-2017", 83),
)).toDF("city", "month", "sales")
df.show()
val mask = udf( (s : String) => {
  "*** Masked ***"
})
df.withColumn("city", mask($"city")).show`

您的语句

mask.foreach(c => base.withColumn(c, regexp_replace(col(c), "^.*?$", "*** Masked ***" ) ) )

将返回听起来不太好的List[org.apache.spark.sql.DataFrame]

您可以使用selectExpr并使用:

生成regexp_replace表达式
base.show
+---+----+-----+-------+
| id|name|  age|address|
+---+----+-----+-------+
|  1|abcd|12345|  KT10 |
|  2|qazx|98765|  AD12d|
+---+----+-----+-------+
val mask = Seq("name", "age")
val expr = df.columns.map { col =>
   if (mask.contains(col) ) s"""regexp_replace(${col}, "^.*", "** Masked **" ) as ${col}"""
   else col
 }

这将对序列mask

中存在的列生成带有Regex_replace的表达式
Array[String] = Array(id, regexp_replace(name, "^.*", "** Masked **" ) as name, regexp_replace(age, "^.*", "** Masked **" ) as age, address)

现在您可以在生成序列上使用selectExpr

base.selectExpr(expr: _*).show
+---+------------+------------+-------+
| id|        name|         age|address|
+---+------------+------------+-------+
|  1|** Masked **|** Masked **|  KT10 |
|  2|** Masked **|** Masked **|  AD12d|
+---+------------+------------+-------+

相关内容

  • 没有找到相关文章

最新更新