Spark-Scala-根据条件从数据帧中删除列
我们有一个特殊的需求,在这个需求中,我必须从一个只有一个唯一值的Spark-Scala-根据条件从数据帧中删除列,scala,apache-spark,Scala,Apache Spark,我们有一个特殊的需求,在这个需求中,我必须从一个只有一个唯一值的dataframe中删除列。下面是我们正在做的 val rawdata = spark.read.format("csv").option("header","true").option("inferSchema","true").load(filename) 随后,为了在所有列中找到唯一的值,我们使用spark中支持的HyperLog++算法 val cd_cols = rawdata.select(rawdata.colum
dataframe
中删除列。下面是我们正在做的
val rawdata = spark.read.format("csv").option("header","true").option("inferSchema","true").load(filename)
随后,为了在所有列中找到唯一的值,我们使用spark中支持的HyperLog++
算法
val cd_cols = rawdata.select(rawdata.columns.map(column => approxCountDistinct(col(column)).alias(column)): _*)
输出是
scala> cd_cols.show
+----+----------+---------+---+---------+--------------+---------+----------+----------------+---------+--------------+-------------+
| ID|First Name|Last Name|Age|Attrition|BusinessTravel|DailyRate|Department|DistanceFromHome|Education|EducationField|EmployeeCount|
+----+----------+---------+---+---------+--------------+---------+----------+----------------+---------+--------------+-------------+
|1491| 172| 154| 43| 2| 3| 913| 3| 30| 1| 6| 1|
+----+----------+---------+---+---------+--------------+---------+----------+----------------+---------+--------------+-------------+
请注意,我有两个列,其唯一值为1。我想创建另一个dataframe
,它包含除这两列之外的所有列(Education
和EmployeeCount
)
我尝试使用for循环,但不太高兴,也尝试了
cd_cols.columns.filter(colName => cd_cols.filter(colName) <= 1)
cd_cols.columns.filter(colName=>cd_cols.filter(colName)您可以尝试以下命令:
df.selectExpr(df.first().getValuesMap[Int](df.columns).filter(_._2 != 1).keys.toSeq: _*).show
这里,我们首先获取数据帧的第一行
,并使用getValueMap
和列名将其转换为一个映射,然后只过滤值不是1的列。如果您想从最初尝试的内容继续进行,以下操作也应该有效。另外,请注意,在Spark 2.0之后,您可以将列表传递到drop并以这种方式删除列。这可能会更清楚地了解您正在做什么
或者最坏的情况是另一种方式
这应该适用于大多数spark版本
val keptCols: Seq[Column] = df.columns
.map(c => (c, df.select(c).first.getLong(0)))
.filter{case (c, v) => v!=1}
.map{case (c, v) => df(c)}
.toSeq
df.select(keptCols: _*).show
对于>Spark 2.0
val droppedCols: Seq[String] = df.columns
.map(c => (c, df.select(c).first.getLong(0)))
.filter{case (c, v) => v==1}
.map{case (c, v) => c}
.toSeq
df.drop(droppedCols: _*).show
两者都应该使用相同的结果。如果您不想要这些列,那么只需选择其余的列。@RameshMaharjan,我现在还不知道。这完全取决于上一条语句返回的唯一值。我无法对这些列进行“硬编码”。这意味着您要删除那些有1个值的列?@RameshMaharjan是的。删除只有一个唯一值的列是真的吗?通过查看一行,我们可以知道要删除哪些列?我的意思是说,如果一行中的一列为1,那么该特定列中的所有其他行都将为1,这是对称的吗?这很有魅力。我必须做的一个小更正是将[Int]改为[Long].val select_cols=df.selectExpr(df.first().getValuesMap[Long](df.columns).filter(u._2!=1).keys.toSeq:*)非常感谢您的帮助什么是u._2?这是列名吗?u.2是元组的第二个元素