为啥 R lubridate::duration 数据类型使用 sparklyr 转换为 spark 中的字符?

Posted

技术标签:

【中文标题】为啥 R lubridate::duration 数据类型使用 sparklyr 转换为 spark 中的字符?【英文标题】:Why does R lubridate::duration datatype convert to character in spark using sparklyr?为什么 R lubridate::duration 数据类型使用 sparklyr 转换为 spark 中的字符? 【发布时间】:2021-05-19 12:55:37 【问题描述】:

我正在使用 sparklyr 包转换我的原始 R 代码以使其适用于 Spark。我使用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
---

使用sparklyr 对 Spark 数据帧执行完全相同的转换会产生错误,因为持续时间数据类型会自动转换为字符串数据类型。代码和错误显示在以下示例中。本地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
---

是否可以使用 sparklyr 在 Spark 中使用 lubridate::duration 数据类型?如果没有,有没有办法绕过转换为字符串,结果是天数为双倍?感谢所有帮助。

【问题讨论】:

【参考方案1】:

您可以使用 build in hive 功能来执行此操作:

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

【讨论】:

您好 Kresten,感谢您提供的替代方法。我也使用了这种替代方法,但我的问题集中在为什么会发生这种情况。应该支持 lubridate 包,但显然不支持 lubridate 持续时间数据类型。

以上是关于为啥 R lubridate::duration 数据类型使用 sparklyr 转换为 spark 中的字符?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 R 使用基数排序?

R.styleable 无法解决,为啥?

为啥 NegativeBinomialP 与 R 相比给出不同的系数?

为啥 R 无法加载共享对象?

为啥 Android Studio 将我所有的引用从 R 更改为 android.R?

为啥 Android Studio 将我所有的引用从 R 更改为 android.R?