pyspark"之间" function:时间戳上的范围搜索不包括在内

时间:2017-04-14 01:10:51

标签: python datetime range pyspark between

pyspark'之间'函数不包含时间戳输入。

例如,如果我们想要两个日期之间的所有行,比如说,' 2017-04-13'和' 2017-04-14'然后它执行"排除"当日期作为字符串传递时搜索。即,它省略了' 2017-04-14 00:00:00'字段

然而,该文件似乎暗示它是包容性的([http://spark.apache.org/docs/2.1.0/api/python/pyspark.sql.html],但没有关于时间戳的参考)

当然,一种方法是从上限添加一个微秒并将其传递给函数。但是,不是一个很好的修复。任何干净的包容性搜索方式?

示例:

import pandas as pd
from pyspark.sql import functions as F
... sql_context creation ...
test_pd=pd.DataFrame([{"start":'2017-04-13 12:00:00', "value":1.0},{"start":'2017-04-14 00:00:00', "value":1.1}])
test_df = sql_context.createDataFrame(test_pd).withColumn("start", F.col("start").cast('timestamp'))
test_df.show()

+--------------------+-----+
|               start|value|
+--------------------+-----+
|2017-04-13 12:00:...|  1.0|
|2017-04-14 00:00:...|  1.1|
+--------------------+-----+

test_df.filter(F.col("start").between('2017-04-13','2017-04-14')).show()

+--------------------+-----+
|               start|value|
+--------------------+-----+
|2017-04-13 12:00:...|  1.0|
+--------------------+-----+

3 个答案:

答案 0 :(得分:3)

找到答案。 pyspark"之间"函数在处理时间戳输入时不一致。

  1. 如果您在没有时间的情况下以字符串格式提供输入,它将执行独占搜索(不是我们对上面链接的文档所期望的)。
  2. 如果您将输入提供为日期时间对象或具有确切时间(例如,' 2017-04-14 00:00:00',则它会执行包含性搜索。
  3. 对于上面的示例,这里是独占搜索的输出(使用pd.to_datetime):

    test_df.filter(F.col("start").between(pd.to_datetime('2017-04-13'),pd.to_datetime('2017-04-14'))).show()
    
    +--------------------+-----+
    |               start|value|
    +--------------------+-----+
    |2017-04-13 12:00:...|  1.0|
    |2017-04-14 00:00:...|  1.1|
    +--------------------+-----+
    

    同样,如果我们以字符串格式提供日期和时间,它似乎执行包容性搜索:

    test_df.filter(F.col("start").between('2017-04-13 12:00:00','2017-04-14 00:00:00')).show()
    
    +--------------------+-----+
    |               start|value|
    +--------------------+-----+
    |2017-04-13 12:00:...|  1.0|
    |2017-04-14 00:00:...|  1.1|
    +--------------------+-----+
    

答案 1 :(得分:2)

.between()方法始终包含在内。您的示例中的问题是,当您将字符串传递给.between()方法时,它也将您的数据视为字符串。对于字符串比较,“ 2017-04-14 00:00:00”严格大于“ 2017-04-14”,因为前者比后者长,因此这就是示例中第二个日期被过滤掉的原因。为避免“不一致”,您应按以下所示将日期时间格式的参数传递给.between():

filtered_df = (test_df.filter(F.col("start")
                .between(dt.strptime('2017-04-13 12:00:00', '%Y-%m-%d %H:%M:%S'), 
                         dt.strptime('2017-04-14 00:00:00', '%Y-%m-%d %H:%M:%S'))))

这将产生预期的结果:

+--------------------+-----+
|               start|value|
+--------------------+-----+
|2017-04-13 12:00:...|  1.0|
|2017-04-14 00:00:...|  1.1|
+--------------------+-----+

答案 2 :(得分:0)

明确一点,如果您想从单个日期获取数据,最好指定确切时间

ex) 仅检索一天的数据 (2017-04-13)

test_df.filter(F.col("start").between('2017-04-13 00:00:00','2017-04-13 23:59:59.59') 

cf) 如果您将日期设置为 '2017-04-13', '2017-04-14' 这将包括 2017-04-14 00:00:00 数据,这在技术上不是数据因为是 2017-04-14 的数据,所以你想拉出来。