r - 为什么 R lubridate::duration 数据类型使用 sparklyr 转换为 spark 中的字符?
问题描述
我正在使用包转换我的原始 R 代码以使其适用于 Spark sparklyr
。我使用lubridate
包来计算两个日期之间的天数。在 R 中,这会产生duration
数据类型,然后可以将其转换为数字数据类型,如下面的示例所示。
# Load packages
library(sparklyr)
library(dplyr)
library(lubridate)
# Create dataframe with start and end date
df <- tibble(start = ymd("20210101"),
end = ymd("20210105"))
df
---
# A tibble: 1 x 2
start end
<date> <date>
1 2021-01-01 2021-01-05
---
# Calculate duration and convert to numeric using R dataframe
df %>%
mutate(dur = end - start,
dur_num = as.numeric(dur))
---
# A tibble: 1 x 4
start end dur dur_num
<date> <date> <drtn> <dbl>
1 2021-01-01 2021-01-05 4 days 4
---
在 Spark 数据帧上使用完全相同的转换sparklyr
会产生错误,因为持续时间数据类型会自动转换为字符串数据类型。代码和错误显示在以下示例中。从本地 R 转移到 Spark 时,请忽略由于时区差异引起的日期变化。
## Connect to local Spark cluster
sc <- spark_connect(master = "local", version = "3.0")
# Copy dataframe to Spark
df_spark <- copy_to(sc, df)
# Calculate duration using Spark dataframe
df_spark %>%
mutate(dur = end - start)
---
# Source: spark<?> [?? x 3]
start end dur
<date> <date> <chr>
1 2020-12-31 2021-01-04 4 days
---
# Calculate duration and convert to numeric using Spark dataframe
df_spark %>%
mutate(dur = end - start,
dur_num = as.numeric(dur))
---
Error: org.apache.spark.sql.AnalysisException: cannot resolve 'CAST(q01.`dur` AS DOUBLE)' due to data type
mismatch: cannot cast interval to double; line 1 pos 30;
'Project [start#58, end#59, dur#280, cast(dur#280 as double) AS dur_num#281]
+- SubqueryAlias q01
+- Project [start#58, end#59, subtractdates(end#59, start#58) AS dur#280]
+- SubqueryAlias df
+- LogicalRDD [start#58, end#59], false
---
是否可以使用lubridate::duration
Spark 中的数据类型sparklyr
?如果没有,有没有办法绕过转换为字符串,结果是天数为双倍?感谢所有帮助。
解决方案
您可以使用内置配置单元功能来执行此操作:
df_spark %>%
mutate(dur = datediff(end, start))
# Source: spark<?> [?? x 3]
start end dur
<date> <date> <int>
1 2021-01-01 2021-01-05 4
在进行差异之前是否是一个日期时间对象,将日期时间对象转换为数字,例如
df <- tibble(start = ymd_hms("20210101 00:00:00"),
end = ymd_hms("20210105 00:00:00"))
df_spark <- copy_to(sc, df)
df_spark %>%
mutate(dur = (as.numeric(end) - as.numeric(start))/(3600*24))
# Source: spark<?> [?? x 3]
start end dur
<dttm> <dttm> <dbl>
1 2021-01-01 00:00:00 2021-01-05 00:00:00 4
推荐阅读
- sql - JPA Criteria 在通用操作中插入一个没有所有值的新对象
- windows - 无法打开端口时如何在Windows上杀死端口上的进程?
- r - 使用特定范围的列作为 x 轴绘制多个散点图
- javascript - 用户单击提交后,如何在我的注册页面上输出“已确认”消息?
- database - Oracle err=918,unixUDBC,instantclinet
- javascript - CKEditor 5 工具栏显示为灰色
- php - 添加处理程序在 htaccess
- python - 出现错误:尝试训练机器学习模型时 Python 预处理失败
- sql-server - 该表不支持“updatedAt”系统属性
- php - 在 Laravel Nova 中使用带有指标的模型(资源)属性(访问器)