Scala 如何在spark的数据框中“负选择”列

Scala 如何在spark的数据框中“负选择”列,scala,apache-spark,dataframe,apache-spark-sql,Scala,Apache Spark,Dataframe,Apache Spark Sql,我不明白,但我想很简单。我有一个spark数据帧df。此df有A、B和C列。现在假设我有一个数组,其中包含此df列的名称: column_names = Array("A","B","C") 我希望以这样一种方式执行df.select,即我可以指定不选择哪些列。 示例:假设我不想选择B列。我尝试了 df.select(column_names.filter(_!="B")) 但这不起作用,因为 org.apache.spark.sql.DataFrame 无法应用于数组[字符串] 所以,它说

我不明白,但我想很简单。我有一个spark数据帧df。此df有A、B和C列。现在假设我有一个数组,其中包含此df列的名称:

column_names = Array("A","B","C")
我希望以这样一种方式执行df.select,即我可以指定不选择哪些列。 示例:假设我不想选择B列。我尝试了

df.select(column_names.filter(_!="B"))
但这不起作用,因为

org.apache.spark.sql.DataFrame 无法应用于数组[字符串]

所以,它说它应该与Seq一起工作。然而,尝试

df.select(column_names.filter(_!="B").toSeq)
导致

org.apache.spark.sql.DataFrame 无法应用于Seq[String]


我做错了什么?

好吧,这很难看,但是这个快速的spark shell课程展示了一些有用的东西:

scala> val myRDD = sc.parallelize(List.range(1,10))
myRDD: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[17] at parallelize at <console>:21

scala> val myDF = myRDD.toDF("a")
myDF: org.apache.spark.sql.DataFrame = [a: int]

scala> val myOtherRDD = sc.parallelize(List.range(1,10))
myOtherRDD: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[20] at parallelize at <console>:21

scala> val myotherDF = myRDD.toDF("b")
myotherDF: org.apache.spark.sql.DataFrame = [b: int]

scala> myDF.unionAll(myotherDF)
res2: org.apache.spark.sql.DataFrame = [a: int]

scala> myDF.join(myotherDF)
res3: org.apache.spark.sql.DataFrame = [a: int, b: int]

scala> val twocol = myDF.join(myotherDF)
twocol: org.apache.spark.sql.DataFrame = [a: int, b: int]

scala> val cols = Array("a", "b")
cols: Array[String] = Array(a, b)

scala> val selectedCols = cols.filter(_!="b")
selectedCols: Array[String] = Array(a)

scala> twocol.select(selectedCols.head, selectedCols.tail: _*)
res4: org.apache.spark.sql.DataFrame = [a: int]
为需要变量的函数提供变量在中处理。select的签名用于确保所选列的列表不为空,这使得从所选列列表到所选列的转换更加复杂。

您可以使用以下方法:

斯卡拉:

案例类Pointx:Int,y:Int val df=sqlContext.createDataFramePoint0,0::Point1,2::Nil 杜比 Python:

df=sc.parallelize[0,0,1,2].toDF[x,y] 杜比 数据帧[x:bigint]
可以执行以下操作

它使用Spark的功能使用正则表达式选择列。 使用消极的前瞻性表达

在这种情况下,dataframe具有列a、b、c和正则表达式,不包括列表中的列b

注意:您需要使用spark.sql.parser.quotedRegexColumnNames=true会话设置为列名查找启用regexp。需要Spark 2.3+

select `^(?!b).*` 
from (
   select 1 as a, 2 as b, 3 as c
)

我也遇到了同样的问题,通过这种方式解决了oaffdf是一个数据帧:

val dropColNames = Seq("col7","col121")
val featColNames = oaffdf.columns.diff(dropColNames)
val featCols = featColNames.map(cn => org.apache.spark.sql.functions.col(cn))
val featsdf = oaffdf.select(featCols: _*)
在pyspark中,您可以

df.select(list(set(df.columns) - set(["B"])))
使用多行还可以执行以下操作

cols = df.columns
cols.remove("B")
df.select(cols)
对于Spark v1.4及更高版本,使用drop*cols-

返回不包含指定列的新数据帧

范例-

df.drop('age').collect()
对于Spark v2.3及更高版本,您也可以使用colRegexcolName来实现-

根据指定为正则表达式的列名选择列,并将其返回为

范例-

df = spark.createDataFrame([("a", 1), ("b", 2), ("c",  3)], ["Col1", "Col2"])
df.select(df.colRegex("`(Col1)?+.+`")).show()
参考-


对于旧版本的Spark,获取dataframe中的列列表,然后使用set操作删除要从中删除的列,然后使用select选择结果列表。

谢谢!我没有意识到这一点,但我仍然使用spark 1.3。我想知道是否有任何方法可以按列位置进行拖放,例如df.drop1或df。dropcol1@DavidArenburgdf.dropdf.columnsi?谢谢!好主意,不过它毕竟需要方括号,如df.dropdf.columns[i]@DavidArenburg-Python?:为什么不使用.drop?虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-更新答案。谢谢你的反馈。我最初的答案是5年前的,所以当时我手头没有Spark 2.3:
df = spark.createDataFrame([("a", 1), ("b", 2), ("c",  3)], ["Col1", "Col2"])
df.select(df.colRegex("`(Col1)?+.+`")).show()