我有这样的数据:
+---+------+
| 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|
+---+------+----------+
我可以用pandas
和strptime
得到它。下面是我的代码:
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)
现在,主要问题是我想使用pandas
和list
来avoid
,因为我将处理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的when
和otherwise
很容易实现这个
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)。但这是一种"标准"在这里,所以我不认为在这里使用有什么不妥。
格式是否正确?使用yyMMdd
和to_date
进行解析,dd-MM-yyyy
和date_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')))