将字符串转换为标识正确年份的确切日期



我有这样的数据:

+---+------+                                                                    
| id|   col|
+---+------+
|  1|210927|
|  2|210928|
|  3|210929|
|  4|210930|
|  5|211001|
+---+------+

我希望输出如下所示:

+---+------+----------+
| id|   col|   t_date1|
+---+------+----------+
|  1|210927|27-09-2021|
|  2|210928|28-09-2021|
|  3|210929|29-09-2021|
|  4|210930|30-09-2021|
|  5|211001|01-10-2021|
+---+------+----------+   

我可以用pandasstrptime得到它。下面是我的代码:

pDF= df.toPandas()
valuesList = pDF['col'].to_list()
modifiedList = list()

for i in valuesList:
...  modifiedList.append(datetime.strptime(i, "%y%m%d").strftime('%d-%m-%Y'))

pDF['t_date1']=modifiedList

df = spark.createDataFrame(pDF)

现在,主要问题是我想使用pandaslistavoid,因为我将处理millions甚至billions的数据,而pandas在涉及大数据时减慢了过程。

我在spark中尝试了各种方法,如unixtime,to_date,timestamp,我需要的格式,但没有运气,因为strptime只适用于字符串,我不能直接在列上使用它。我不愿意创建UDF,因为它们也很慢。

主要问题是确定确切的年份,我不能在spark做,但我希望只使用spark实现它。需要改变什么?我哪里做错了?

根据Pythondatetime.strptime

# Open Group specification for strptime() states that a %y
#value in the range of [00, 68] is in the century 2000, while
#[69,99] is in the century 1900
if year <= 68:
year += 2000
else:
year += 1900

用PySpark的whenotherwise很容易实现这个

from pyspark.sql import functions as F
(df
.withColumn('y', F.substring('col', 0, 2).cast('int'))
.withColumn('y', F
.when(F.col('y') <= 68, F.col('y') + 2000)
.otherwise(F.col('y') + 1900)
)
.withColumn('t_date', F.concat('y', F.regexp_replace('col', '(d{2})(d{2})(d{2})', '-$2-$3')))
.show()
)
# Output
# +---+------+----+----------+
# | id|   col|   y|    t_date|
# +---+------+----+----------+
# |  1|210927|2021|2021-09-27|
# |  2|910927|1991|1991-09-27|
# +---+------+----+----------+

从技术上讲,你可以整天争论这种方法(0-68然后69-99)。但这是一种"标准"在这里,所以我不认为在这里使用有什么不妥。

格式是否正确?使用yyMMddto_date进行解析,dd-MM-yyyydate_format进行格式化应该可以工作:

import pyspark.sql.functions as f
df.withColumn('t_date', f.date_format(f.to_date('col', 'yyMMdd'), 'dd-MM-yyyy')).show()
+---+------+----------+
| id|   col|    t_date|
+---+------+----------+
|  1|210927|27-09-2021|
|  2|210928|28-09-2021|
|  3|210929|29-09-2021|
|  4|210930|30-09-2021|
|  5|211001|01-10-2021|
+---+------+----------+

如果col不是字符串类型,先转换为字符串:

df.withColumn('t_date', f.date_format(f.to_date(f.col('col').cast('string'), 'yyMMdd'), 'dd-MM-yyyy')).show()

还有另一种方法:

(df.assign(t_date1 = pd.to_datetime('20' + df['Col'].astype(str)
,format = '%Y/%m/%d').dt.strftime('%d-%m-%Y')))

相关内容

  • 没有找到相关文章

最新更新