如何使用pyspark

时间:2016-08-13 03:31:52

标签: apache-spark pyspark dayofweek

我有一个数据帧log_df: enter image description here

我根据以下代码生成新的数据框:

from pyspark.sql.functions import split, regexp_extract 
split_log_df = log_df.select(regexp_extract('value', r'^([^\s]+\s)', 1).alias('host'),
                          regexp_extract('value', r'^.*\[(\d\d/\w{3}/\d{4}:\d{2}:\d{2}:\d{2} -\d{4})]', 1).alias('timestamp'),
                          regexp_extract('value', r'^.*"\w+\s+([^\s]+)\s+HTTP.*"', 1).alias('path'),
                          regexp_extract('value', r'^.*"\s+([^\s]+)', 1).cast('integer').alias('status'),
                          regexp_extract('value', r'^.*\s+(\d+)$', 1).cast('integer').alias('content_size'))
split_log_df.show(10, truncate=False)

新数据框如下: enter image description here

我需要另一个列显示每周的日子,创建它的最佳方式是什么?理想情况下,只需在选择中添加类似udf的字段。

非常感谢。

更新:我的问题与评论中的问题不同,我需要的是根据log_df中的字符串进行计算,而不是基于评论的时间戳,所以这不是一个重复的问题。感谢。

6 个答案:

答案 0 :(得分:16)

我建议采用一种不同的方法

from pyspark.sql.functions import date_format
df.select('capturetime', date_format('capturetime', 'u').alias('dow_number'), date_format('capturetime', 'E').alias('dow_string'))
df3.show()

它给出了......

+--------------------+----------+----------+
|         capturetime|dow_number|dow_string|
+--------------------+----------+----------+
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|

答案 1 :(得分:2)

从 Spark 2.3 开始,你可以使用 dayofweek 函数 https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.sql.functions.dayofweek.html

from pyspark.sql.functions import dayofweek
df.withColumn('day_of_week', dayofweek('my_timestamp'))

然而,这将一周的开始定义为星期日 = 1

如果你不想那样,而是要求 Monday = 1,那么你可以做一个不雅的软糖,比如在使用 dayofweek 函数之前减去 1 天,或者像这样修改结果

from pyspark.sql.functions import dayofweek
df.withColumn('day_of_week', ((dayofweek('my_timestamp')+5)%7)+1)

答案 2 :(得分:0)

我终于自己解决了这个问题,这是完整的解决方案:

  1. import date_format,datetime,DataType
  2. 首先,修改regexp以提取01 / Jul / 1995
  3. 使用func
  4. 将01 / Jul / 1995转换为DateType
  5. 创建一个udf dayOfWeek,以简短的格式(星期一,星期二,...)获取工作日
  6. 使用udf将DateType 01 / Jul / 1995转换为星期六即星期六 enter image description here
  7. 我对我的解决方案不满意,因为它似乎是如此曲折,如果有人能提出更优雅的解决方案,我将不胜感激,谢谢你。

答案 3 :(得分:0)

我这样做是为了从平日起的工作日:

def get_weekday(date):
    import datetime
    import calendar
    month, day, year = (int(x) for x in date.split('/'))    
    weekday = datetime.date(year, month, day)
    return calendar.day_name[weekday.weekday()]

spark.udf.register('get_weekday', get_weekday)

使用示例:

df.createOrReplaceTempView("weekdays")
df = spark.sql("select DateTime, PlayersCount, get_weekday(Date) as Weekday from weekdays")

enter image description here

答案 4 :(得分:0)

由于SPARK 1.5.0具有date_format函数,该函数接受格式作为参数。此格式从时间戳返回星期几的名称:

select date_format(my_timestamp, 'EEEE') from ....

结果:例如“星期二”

How to get day of week in SparkSQL?

答案 5 :(得分:0)

这对我有用:

重新创建与您的示例类似的数据:

df = spark.createDataFrame(\
    [(1, "2017-11-01 22:05:01 -0400")\
     ,(2, "2017-11-02 03:15:16 -0500")\
     ,(3, "2017-11-03 19:32:24 -0600")\
      ,(4, "2017-11-04 07:47:44 -0700")\
    ], ("id", "date"))

df.toPandas()
    id  date
0   1   2017-11-01 22:05:01 -0400
1   2   2017-11-02 03:15:16 -0500
2   3   2017-11-03 19:32:24 -0600
3   4   2017-11-04 07:47:44 -0700

创建lambda函数来处理到星期的转换

funcWeekDay =  udf(lambda x: datetime.strptime(x, '%Y-%m-%d').strftime('%w'))
  • 将日期提取到shortdate列中
  • 使用lambda函数使用weeday创建列
  • 删除shortdate

代码:

from pyspark.sql.functions import udf,col
    from datetime import datetime


df=df.withColumn('shortdate',col('date').substr(1, 10))\
     .withColumn('weekDay', funcWeekDay(col('shortdate')))\
     .drop('shortdate')

结果:

df.toPandas()
    id  date                     weekDay
0   1   2017-11-01 22:05:01 -0400   3
1   2   2017-11-02 03:15:16 -0500   4
2   3   2017-11-03 19:32:24 -0600   5
3   4   2017-11-04 07:47:44 -0700   6