【问题标题】:Filtering a spark dataframe based on date根据日期过滤火花数据框
【发布时间】:2015-11-06 19:41:33
【问题描述】:

我有一个数据框

date, string, string

我想选择某个时期之前的日期。我试过以下没有运气

 data.filter(data("date") < new java.sql.Date(format.parse("2015-03-14").getTime))

我收到一条错误提示

org.apache.spark.sql.AnalysisException: resolved attribute(s) date#75 missing from date#72,uid#73,iid#74 in operator !Filter (date#75 < 16508);

据我所知,查询不正确。谁能告诉我查询的格式应该如何?

我检查了数据框中的所有条目是否都有值 - 它们确实如此。

【问题讨论】:

    标签: apache-spark apache-spark-sql


    【解决方案1】:

    以下解决方案自 spark 1.5 起适用:

    对于低于:

    // filter data where the date is lesser than 2015-03-14
    data.filter(data("date").lt(lit("2015-03-14")))      
    

    对于大于:

    // filter data where the date is greater than 2015-03-14
    data.filter(data("date").gt(lit("2015-03-14"))) 
    

    对于相等,您可以使用equalTo===

    data.filter(data("date") === lit("2015-03-14"))
    

    如果您的DataFrame 日期列是StringType 类型,您可以使用to_date 函数对其进行转换:

    // filter data where the date is greater than 2015-03-14
    data.filter(to_date(data("date")).gt(lit("2015-03-14"))) 
    

    您还可以使用year 函数根据年份进行过滤:

    // filter data where year is greater or equal to 2016
    data.filter(year($"date").geq(lit(2016))) 
    

    【讨论】:

    • spark 中的日期列是否有类似between 的选项?我也有 'dd/MM/yyyy' 格式的日期。
    • @Sivailango 当然,它是介于两者之间的过滤器,请查看我的答案here
    • df.select(df("ID"), date_format(df("Week_Ending_Date"), "yyyy-MM-dd")) .filter(date_format(df("Week_Ending_Date"), "yyyy-MM-dd").between("2015-07-05", "2015-09-02")) 是吗?我也在寻找你的另一个答案stackoverflow.com/questions/33938806/…
    • 有什么办法可以告诉 gt o lt 像现在一样 - 5 个月?或者我只需要计算该日期并将其作为字符串提供给函数
    • 如果你想使用当前日期和日期差异,比较日期会有所不同。
    【解决方案2】:

    不要按照其他答案中的建议使用它

    .filter(f.col("dateColumn") < f.lit('2017-11-01'))
    

    但是用这个代替

    .filter(f.col("dateColumn") < f.unix_timestamp(f.lit('2017-11-01 00:00:00')).cast('timestamp'))
    

    这将使用TimestampType 而不是StringType,这在某些情况下会更高效。例如 Parquet 谓词下推仅适用于后者。

    【讨论】:

      【解决方案3】:

      我发现最易读的表达方式是使用 sql 表达式:

      df.filter("my_date < date'2015-01-01'")
      

      我们可以通过查看.explain() 的物理计划来验证它是否正确

      +- *(1) Filter (isnotnull(my_date#22) && (my_date#22 < 16436))
      

      【讨论】:

      • 这对我不起作用,但 .filter("effectivedate > to_date('1900-02-02')") 确实有效(对于与我相关的情况)。很可能我需要为给定的解决方案加载一些库才能工作。但总而言之,这是最好的答案。
      • 奇怪 - 它应该在 vanilla pyspark 中工作。
      【解决方案4】:

      在 PySpark(python) 中,选项之一是将列设置为 unix_timestamp 格式。我们可以将字符串转换为 unix_timestamp 并指定格式,如下所示。 注意我们需要导入 unix_timestamp 和 lit 函数

      from pyspark.sql.functions import unix_timestamp, lit
      
      df.withColumn("tx_date", to_date(unix_timestamp(df_cast["date"], "MM/dd/yyyy").cast("timestamp")))
      

      现在我们可以应用过滤器了

      df_cast.filter(df_cast["tx_date"] >= lit('2017-01-01')) \
             .filter(df_cast["tx_date"] <= lit('2017-01-31')).show()
      

      【讨论】:

        【解决方案5】:
        df=df.filter(df["columnname"]>='2020-01-13')
        

        【讨论】:

          【解决方案6】:

          我们也可以在过滤器中使用 SQL 类型的表达式:


          注意 -> 这里我展示了两个条件和一个未来的日期范围 参考:


          ordersDf.filter("order_status = 'PENDING_PAYMENT' AND order_date BETWEEN '2013-07-01' AND '2013-07-31' ")
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-10-20
            相关资源
            最近更新 更多