检查Spark DataFrame中每列是否具有特定的值

4
我们可以使用Spark-SQL或Scala来检查一个Spark数据框中的每一列是否都包含某个字符串(例如"Y")吗?
我尝试过以下方法,但是不认为它正常工作。
df.select(df.col("*")).filter("'*' =='Y'")

谢谢,Sai

你目前尝试了什么,结果如何?有什么不起作用的地方吗?似乎这个问题比较抽象。请提供你尝试过的代码片段。 - Ram Ghadiyaram
你好Ram,已经将代码片段添加到了问题中。 - Bharath
3个回答

5
您可以这样做,以保留所有列都包含“Y”的行:
//Get all columns
val columns: Array[String] = df.columns

//For each column, keep the rows with 'Y'
val seqDfs: Seq[DataFrame] = columns.map(name => df.filter(s"$name == 'Y'"))

//Union all the dataframes together into one final dataframe
val output: DataFrame = seqDfs.reduceRight(_ union _)

你好Sohum。谢谢你。虽然它在某些部分上可以工作,但当我尝试将其写入文件时,它会多次重复相同的输出。 - Bharath
1
问题在于,如果您有一些行,并且该行的两列具有“Y”值,则结果数据框中将有两个相同的行。如果一行的三列具有“Y”值,则结果数据框中将有三个相同的行。 - Andrei Stankevich

3
您可以使用数据帧方法columns来获取所有列名。
val columnNames: Array[String] = df.columns

然后在循环中添加所有的过滤器

var filteredDf = df.select(join5.col("*"))

for(name <- columnNames) {
    filteredDf = filteredDf.filter(s"$name =='Y'")
}

或者你可以使用同样的方法创建一个SQL查询


你好,Andrei,感谢您的回复,我非常感激。不过,我想确认每一列中的值是否包含“Y”,而不是列名。 - Bharath
filter(s"$name =='Y'") 此过滤器检查具有名称 $name 的列的值是否等于 'Y'。如果您想要检查“包含”,则可以使用 filter(s"$name like '%Y%' ")。表达式 s"$name like '%Y%'" 检查特定列的列值,而不是列名。 - Andrei Stankevich
谢谢Andrei。我会尝试并告诉你结果。感谢你的努力。 - Bharath
你好Andrei。我尝试了这个解决方案,但它似乎不能正确地完成任务。 - Bharath
你能发布带有解释的代码吗?解释一下你期望它如何工作。 - Andrei Stankevich
这里的问题是,多个过滤器是多个AND的连接,因此您最终会得到每一列中值都等于Y的行。 - Michael Brenndoerfer

1
如果您想过滤每一行,其中任何一个列等于1(或其他任何值),可以动态创建如下查询:
cols = [col(c) == lit(1) for c in patients.columns]
query = cols[0]

for c in cols[1:]:
    query |= c

df.filter(query).show()

这段话有点啰嗦,但很清楚地说明了正在发生的事情。更优雅的版本应该是:

res = df.filter(reduce(lambda x, y: x | y,  (col(c) == lit(1) for c in cols)))
res.show()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接