Pyspark:根据多个条件过滤数据帧

Posted

技术标签:

【中文标题】Pyspark:根据多个条件过滤数据帧【英文标题】:Pyspark: Filter dataframe based on multiple conditions 【发布时间】:2018-08-24 09:03:30 【问题描述】:

我想首先根据以下条件(d

如果原始数据框DF如下:

+----+----+----+----+---+
|col1|col2|col3|col4|  d|
+----+----+----+----+---+
|   A|  xx|   D|  vv|  4|
|   C| xxx|   D|  vv| 10|
|   A|   x|   A|  xx|  3|
|   E| xxx|   B|  vv|  3|
|   E| xxx|   F| vvv|  6|
|   F|xxxx|   F| vvv|  4|
|   G| xxx|   G| xxx|  4|
|   G| xxx|   G|  xx|  4|
|   G| xxx|   G| xxx| 12|
|   B|xxxx|   B|  xx| 13|
+----+----+----+----+---+

所需的数据框是:

+----+----+----+----+---+
|col1|col2|col3|col4|  d|
+----+----+----+----+---+
|   A|  xx|   D|  vv|  4|
|   A|   x|   A|  xx|  3|
|   E| xxx|   B|  vv|  3|
|   F|xxxx|   F| vvv|  4|
|   G| xxx|   G|  xx|  4|
+----+----+----+----+---+

我尝试过的代码没有按预期工作:

cols=[('A','xx','D','vv',4),('C','xxx','D','vv',10),('A','x','A','xx',3),('E','xxx','B','vv',3),('E','xxx','F','vvv',6),('F','xxxx','F','vvv',4),('G','xxx','G','xxx',4),('G','xxx','G','xx',4),('G','xxx','G','xxx',12),('B','xxxx','B','xx',13)]
df=spark.createDataFrame(cols,['col1','col2','col3','col4','d'])

df.filter((df.d<5)& (df.col2!=df.col4) & (df.col1==df.col3)).show()

+----+----+----+----+---+
|col1|col2|col3|col4|  d|
+----+----+----+----+---+
|   A|   x|   A|  xx|  3|
|   F|xxxx|   F| vvv|  4|
|   G| xxx|   G|  xx|  4|
+----+----+----+----+---+

我应该怎么做才能达到预期的效果?

【问题讨论】:

【参考方案1】:

我迟到了,但有人可能会觉得这很有用。

如果您的条件是列表形式,例如filter_values_list =['value1', 'value2'] 并且您正在过滤单个列,那么您可以这样做:

df.filter(df.colName.isin(filter_values_list)

【讨论】:

【参考方案2】:

更快的方式(没有pyspark.sql.functions

    df.filter((df.d<5)&((df.col1 != df.col3) |
                    (df.col2 != df.col4) & 
                    (df.col1 ==df.col3)))\
    .show()

【讨论】:

这样df必须重复。【参考方案3】:

你也可以像下面这样写(不带pyspark.sql.functions):

df.filter('d<5 and (col1 <> col3 or (col1 = col3 and col2 <> col4))').show()

结果:

+----+----+----+----+---+
|col1|col2|col3|col4|  d|
+----+----+----+----+---+
|   A|  xx|   D|  vv|  4|
|   A|   x|   A|  xx|  3|
|   E| xxx|   B|  vv|  3|
|   F|xxxx|   F| vvv|  4|
|   G| xxx|   G|  xx|  4|
+----+----+----+----+---+

【讨论】:

【参考方案4】:

你的逻辑条件是错误的。 IIUC,你想要的是:

import pyspark.sql.functions as f

df.filter((f.col('d')<5))\
    .filter(
        ((f.col('col1') != f.col('col3')) | 
         (f.col('col2') != f.col('col4')) & (f.col('col1') == f.col('col3')))
    )\
    .show()

为了便于阅读,我将 filter() 步骤分成 2 次调用,但您也可以在一行中完成。

输出:

+----+----+----+----+---+
|col1|col2|col3|col4|  d|
+----+----+----+----+---+
|   A|  xx|   D|  vv|  4|
|   A|   x|   A|  xx|  3|
|   E| xxx|   B|  vv|  3|
|   F|xxxx|   F| vvv|  4|
|   G| xxx|   G|  xx|  4|
+----+----+----+----+---+

【讨论】:

以上是关于Pyspark:根据多个条件过滤数据帧的主要内容,如果未能解决你的问题,请参考以下文章

如何根据pyspark中的行和列条件过滤多行

[基于独立索引向量的多个条件过滤数据帧

根据另一个数据帧过滤 pyspark 数据帧

如何根据来自其他 pyspark 数据帧的日期值过滤第二个 pyspark 数据帧?

需要使用迭代多个列的过滤器值过滤 Spark 数据帧

使用 AND OR 在多个条件下过滤 pyspark