数据框的多条件筛选

28

有人可以解释一下为什么我对这两个表达式的过滤结果不同吗?我正在尝试在两个日期之间进行筛选:

df.filter("act_date <='2017-04-01'" and "act_date >='2016-10-01'")\
  .select("col1","col2").distinct().count()

结果:37M

对比:

df.filter("act_date <='2017-04-01'").filter("act_date >='2016-10-01'")\
  .select("col1","col2").distinct().count()

结果:25M

它们有什么不同?对我来说,它们应该产生相同的结果

2个回答

60

TL;DR 要将多个条件传递给 filterwhere,请使用Column对象和逻辑运算符(&|~) 。详情请参见Pyspark: multiple conditions in when clause

df.filter((col("act_date") >= "2016-10-01") & (col("act_date") <= "2017-04-01"))

您也可以使用单个 SQL 字符串:

df.filter("act_date >='2016-10-01' AND act_date <='2017-04-01'")

实际上使用between更有意义:

df.filter(col("act_date").between("2016-10-01", "2017-04-01"))
df.filter("act_date BETWEEN '2016-10-01' AND '2017-04-01'")

第一种方法甚至不符合要求。在Python中,and 返回:

  • 如果所有表达式都是“真”,则返回最后一个元素。
  • 否则返回第一个“假”的元素。

因此

"act_date <='2017-04-01'" and "act_date >='2016-10-01'"

被评估为真(任何非空字符串都属于真):

"act_date >='2016-10-01'"

1
在第一个情况中
df.filter("act_date <='2017-04-01'" and "act_date >='2016-10-01'")\
  .select("col1","col2").distinct().count()

这个结果是值大于2016-10-01的,也就是说所有在2017-04-01之后的值。

而在第二种情况中

df.filter("act_date <='2017-04-01'").filter("act_date >='2016-10-01'")\
  .select("col1","col2").distinct().count()

结果是2016年10月1日到2017年4月1日之间的值。

1
当我向过滤器添加多个条件时,我会遇到这个错误Py4JError:调用o355.or时发生错误。跟踪: py4j.Py4JException:方法or([class java.lang.String])不存在。 - Lance

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