Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Pyspark检查是否有任何行大于零_Python_Dataframe_Apache Spark_Pyspark_Apache Spark Sql - Fatal编程技术网

Python Pyspark检查是否有任何行大于零

Python Pyspark检查是否有任何行大于零,python,dataframe,apache-spark,pyspark,apache-spark-sql,Python,Dataframe,Apache Spark,Pyspark,Apache Spark Sql,我想过滤掉列表中所有列的零值行 假设我们有下面的df df = spark.createDataFrame([(0, 1, 1, 2,1), (0, 0, 1, 0, 1), (1, 0, 1, 1 ,1)], ['a', 'b', 'c', 'd', 'e']) +---+---+---+---+---+ | a| b| c| d| e| +---+---+---+-

我想过滤掉列表中所有列的零值行

假设我们有下面的df

df = spark.createDataFrame([(0, 1, 1, 2,1), (0, 0, 1, 0, 1), (1, 0, 1, 1 ,1)], ['a', 'b', 'c', 'd', 'e'])
+---+---+---+---+---+                                                           
|  a|  b|  c|  d|  e|
+---+---+---+---+---+
|  0|  1|  1|  2|  1|
|  0|  0|  1|  0|  1|
|  1|  0|  1|  1|  1|
+---+---+---+---+---+
列的列表是['a','b','d',,所以过滤后的数据帧应该是

+---+---+---+---+---+                                                           
|  a|  b|  c|  d|  e|
+---+---+---+---+---+
|  0|  1|  1|  2|  1|
|  1|  0|  1|  1|  1|
+---+---+---+---+---+
这就是我尝试过的

df = df.withColumn('total', sum(df[col] for col in ['a', 'b', 'd']))
df = df.filter(df.total > 0).drop('total')
这对于小数据集很好,但如果列列表很长,并且出现以下错误,则会失败,并出现以下错误

ava.lang.StackOverflowErrorat org.apache.spark.sql.catalyst.analysis.resolvellambdavariables.org$apache$spark$sql$catalyst$analysis$resolvellambdavariables$$resolvelvehigher

我可以想到熊猫udf解决方案,但我的df非常大,这可能是一个瓶颈

编辑:

当使用@Psidom的答案时,我得到以下错误

py4j.protocol.Py4JJavaError:调用o2508.filter时出错。 :java.lang.StackOverflower错误 位于org.apache.spark.sql.catalyst.expressions.Expression.referencesExpression.scala:88 在org.apache.spark.sql.catalyst.expressions.Expression$$anonfun$引用$1.applyExpression.scala:88 在org.apache.spark.sql.catalyst.expressions.Expression$$anonfun$引用$1.applyExpression.scala:88 在scala.collection.TraversableLike$$anonfun$flatMap$1.applyTraversableLike.scala:241 在scala.collection.TraversableLike$$anonfun$flatMap$1.applyTraversableLike.scala:241 位于scala.collection.immutable.List.foreachList.scala:392 在scala.collection.TraversableLike$class.flatMapTraversableLike.scala:241 位于scala.collection.immutable.List.flatMapList.scala:355

在这里可能有用:

df = spark.createDataFrame([(0, 1, 1, 2,1), (0, 0, 1, 0, 1), (1, 0, 1, 1 ,1)], 
     ['a', 'b', 'c', 'd', 'e'])
cols = ['a', 'b', 'd']
使用reduce创建过滤器表达式:

from functools import reduce
predicate = reduce(lambda a, b: a | b, [df[x] != 0 for x in cols])

print(predicate)
# Column<b'(((NOT (a = 0)) OR (NOT (b = 0))) OR (NOT (d = 0)))'>
在这里可能有用:

df = spark.createDataFrame([(0, 1, 1, 2,1), (0, 0, 1, 0, 1), (1, 0, 1, 1 ,1)], 
     ['a', 'b', 'c', 'd', 'e'])
cols = ['a', 'b', 'd']
使用reduce创建过滤器表达式:

from functools import reduce
predicate = reduce(lambda a, b: a | b, [df[x] != 0 for x in cols])

print(predicate)
# Column<b'(((NOT (a = 0)) OR (NOT (b = 0))) OR (NOT (d = 0)))'>

这里有一个不同的解决方案。还没有尝试过大的列集,请让我知道这是否有效

df = spark.createDataFrame([(0, 1, 1, 2,1), (0, 0, 1, 0, 1), (1, 0, 1, 1 ,1)], ['a', 'b', 'c', 'd', 'e'])
df.show()

+---+---+---+---+---+
|  a|  b|  c|  d|  e|
+---+---+---+---+---+
|  0|  1|  1|  2|  1|
|  0|  0|  1|  0|  1|
|  1|  0|  1|  1|  1|
+---+---+---+---+---+

df = df.withColumn("Concat_cols" , F.concat(*list_of_cols)) # concat the list of columns 
df.show()

+---+---+---+---+---+-----------+
|  a|  b|  c|  d|  e|Concat_cols|
+---+---+---+---+---+-----------+
|  0|  1|  1|  2|  1|        012|
|  0|  0|  1|  0|  1|        000|
|  1|  0|  1|  1|  1|        101|
+---+---+---+---+---+-----------+

pattern =  '0' * len(list_of_cols) 

df1 = df.where(df['Concat_cols'] != pattern) # pattern will be 0's and the number will be equal to length of the columns list.
df1.show()

    +---+---+---+---+---+-----------+
    |  a|  b|  c|  d|  e|Concat_cols|
    +---+---+---+---+---+-----------+
    |  0|  1|  1|  2|  1|        012|
    |  1|  0|  1|  1|  1|        101|
    +---+---+---+---+---+-----------+

这里有一个不同的解决方案。还没有尝试过大的列集,请让我知道这是否有效

df = spark.createDataFrame([(0, 1, 1, 2,1), (0, 0, 1, 0, 1), (1, 0, 1, 1 ,1)], ['a', 'b', 'c', 'd', 'e'])
df.show()

+---+---+---+---+---+
|  a|  b|  c|  d|  e|
+---+---+---+---+---+
|  0|  1|  1|  2|  1|
|  0|  0|  1|  0|  1|
|  1|  0|  1|  1|  1|
+---+---+---+---+---+

df = df.withColumn("Concat_cols" , F.concat(*list_of_cols)) # concat the list of columns 
df.show()

+---+---+---+---+---+-----------+
|  a|  b|  c|  d|  e|Concat_cols|
+---+---+---+---+---+-----------+
|  0|  1|  1|  2|  1|        012|
|  0|  0|  1|  0|  1|        000|
|  1|  0|  1|  1|  1|        101|
+---+---+---+---+---+-----------+

pattern =  '0' * len(list_of_cols) 

df1 = df.where(df['Concat_cols'] != pattern) # pattern will be 0's and the number will be equal to length of the columns list.
df1.show()

    +---+---+---+---+---+-----------+
    |  a|  b|  c|  d|  e|Concat_cols|
    +---+---+---+---+---+-----------+
    |  0|  1|  1|  2|  1|        012|
    |  1|  0|  1|  1|  1|        101|
    +---+---+---+---+---+-----------+

如果目的只是检查所有列中出现的0,并且列表导致了问题,那么可能一次将它们合并1000次,然后测试是否出现非零

从pyspark.sql导入函数为F 要测试的所有列或任何列。 columns=df.columns 一次需要连接的列。 拆分=1000 连接到单个列中的1000列的列表 块=[F.concat*列[i*split:i+1*split] 对于rangelencolumns+split-1//split]中的i 此处的表达式替换零以检查结果字符串是否为空。 选择* .whereF.regexp_replaceF.concat*blocks.aliasconcat,0,!= .show10,错
如果目的只是检查所有列中出现的0,并且列表导致了问题,那么可能一次将它们合并1000次,然后测试是否出现非零

从pyspark.sql导入函数为F 要测试的所有列或任何列。 columns=df.columns 一次需要连接的列。 拆分=1000 连接到单个列中的1000列的列表 块=[F.concat*列[i*split:i+1*split] 对于rangelencolumns+split-1//split]中的i 此处的表达式替换零以检查结果字符串是否为空。 选择* .whereF.regexp_replaceF.concat*blocks.aliasconcat,0,!= .show10,错
可以将列作为数组传递给UDF,然后检查所有值是否为零,然后应用过滤器:

from pyspark.sql.types import BooleanType
from pyspark.sql.functions import udf, array, col

all_zeros_udf = udf(lambda arr: arr.count(0) == len(arr), BooleanType())

df = spark.createDataFrame([(0, 1, 1, 2,1), (0, 0, 1, 0, 1), (1, 0, 1, 1 ,1)], ['a', 'b', 'c', 'd', 'e'])

df
.withColumn('all_zeros', all_zeros_udf(array('a', 'b', 'd'))) # pass the columns as array
.filter(~col('all_zeros')) # Filter the columns where all values are NOT zeros
.drop('all_zeros')  # Drop the column
.show()
结果:

+---+---+---+---+---+
|  a|  b|  c|  d|  e|
+---+---+---+---+---+
|  0|  1|  1|  2|  1|
|  1|  0|  1|  1|  1|
+---+---+---+---+---+

可以将列作为数组传递给UDF,然后检查所有值是否为零,然后应用过滤器:

from pyspark.sql.types import BooleanType
from pyspark.sql.functions import udf, array, col

all_zeros_udf = udf(lambda arr: arr.count(0) == len(arr), BooleanType())

df = spark.createDataFrame([(0, 1, 1, 2,1), (0, 0, 1, 0, 1), (1, 0, 1, 1 ,1)], ['a', 'b', 'c', 'd', 'e'])

df
.withColumn('all_zeros', all_zeros_udf(array('a', 'b', 'd'))) # pass the columns as array
.filter(~col('all_zeros')) # Filter the columns where all values are NOT zeros
.drop('all_zeros')  # Drop the column
.show()
结果:

+---+---+---+---+---+
|  a|  b|  c|  d|  e|
+---+---+---+---+---+
|  0|  1|  1|  2|  1|
|  1|  0|  1|  1|  1|
+---+---+---+---+---+

这只适用于列数较少的情况,在我的情况下,列数以千为单位,我得到一个错误,错误日志添加到问题中。这只适用于列数较少的情况,在我的情况下,列数以千为单位,我得到一个错误,问题中添加了错误日志,但不确定将如此长的字符串存储在具有数百万行的df中是否是一个好主意。我认为性能方面的UDF会更好。如果您不想使用这些字符串数据创建新的数据帧,那么您可以将这两个字符串组合成一行代码。df1=df.其中f.concat*列模式工作起来很有魅力,但不确定在具有数百万行的df中存储如此长的字符串是否是一个好主意。我认为性能方面的UDF会更好。如果您不想使用这些字符串数据创建新的数据帧,那么您可以将这两个数据帧组合成一行代码。df1=df.其中f.concat*列谢谢,当我们有数百万行和数千列时,你认为使用udf是一个好主意吗?这取决于你如何使用它。我们每天使用许多自定义项来处理TB的数据。谢谢,当我们有数百万行和数千列时,您认为使用自定义项是一个好主意吗?视情况而定 关于你如何使用它。我们每天使用许多UDF来处理TB的数据。