在String中将String转换为时间戳时处理毫秒数

时间:2017-04-11 12:11:33

标签: r apache-spark casting spark-dataframe sparkr

我在SparkDataFrame中有一个包含时间戳的列,方法如下:

    Start_1
    <chr>
    2016/01/01 10:51:15.304 
    2016/01/01 10:51:15.352

我让Spark在读取文件时推断出模式,这会产生chr作为数据类型。我知道它可以在没有毫秒的情况下工作,产生适当的数据类型和列。但是我也需要毫秒,因此需要将数据类型更改为现有Spark数据框中的时间戳。

以下是我测试过的方法:

因为POSIXct可以在基础R中工作。

    dataloan_time$start_ts <- as.POSIXct(dataloan$Start_1, format = "%Y/%m/%d %H:%M:%OS")

- 不起作用(不知道改变班级)。

此处和其他网站上提到的解决方案提到了投射:

    dataloan_time <- withColumn(dataloan_time, "complete_ts", cast(dataloan$Complete_1, "timestamp"))

对我来说,它正确地转换数据类型,但新列不包含任何数据。

这是head(col)的结果

    start_ts
    <lgl>
    NA  
    NA

收集数据框并更改它将是我找到的最后一个选项,但我想避免这种情况并在Spark Data框架内执行。 还有哪些其他解决方案?理想情况下,它就像第一次尝试(作为POSIXct)。

1 个答案:

答案 0 :(得分:1)

我跳过这个因为我认为这可能是一件简单的事情,我不再认为那么简单了:) 环境=火花:1.5.2

#setup; probably a better way to set this up, oh well, R isn't my first language
d <- c("2016/01/01 10:51:15.304","2016/01/01 10:51:15.352")
df1 <- data.frame(d)
df = createDataFrame(sqlContext, df1)

开始我的困惑:

> as.numeric(as.POSIXct(d))
[1] 1451663475 1451663475

为什么说同一个号码?他们是不同的!!

> print(as.numeric(as.POSIXct(d[1])),digits=20)
[1] 1451663475.3039999008
> print(as.numeric(as.POSIXct(d[2])),digits=20)
[1] 1451663475.3519999981

好的,现在我知道他们的表现方式是一样的,只是按照我的喜好打印 (How to parse milliseconds in R?带领我走上印刷之路)

来自Writing R data frames returned from SparkR:::map

我找到了制作UDF的方法

rows <- SparkR:::flatMap(df, function(x) {
  data <- as.list(x)
  datanew <- append(data,as.POSIXct(data[[1]]))
  args <- list(FUN = list, SIMPLIFY = FALSE, USE.NAMES = FALSE)
  do.call(mapply, append(args, datanew))
})
sdf <- createDataFrame(sqlContext, rows,c("origdt","rownum","newdt"))

如果我们现在对数据帧进行正常打印,我们就不会喜欢我们所看到的了

head(sdf)
                   origdt rownum      newdt
1 2016/01/01 10:51:15.304      1 1451663475
2 2016/01/01 10:51:15.352      2 1451663475

#register it so we can run sql
registerTempTable(sdf,"sdf")

但是,如果我们通过&#34; newdt&#34;我们可以看到它们正在被正确转换

head(sql(sqlContext,"select * from sdf order by newdt"))
                   origdt rownum      newdt
1 2016/01/01 10:51:15.304      1 1451663475
2 2016/01/01 10:51:15.352      2 1451663475

head(sql(sqlContext,"select * from sdf order by newdt desc"))

                   origdt rownum      newdt
1 2016/01/01 10:51:15.352      2 1451663475
2 2016/01/01 10:51:15.304      1 1451663475

我们还可以查看基础rdd数据,以确认转换是否按照我们的预期发生:

print(take(rows,1)[[1]][[3]],digits=20)
[1] 1451663475.3039999008

注意: 我一直把它们保持为双打,因为我认为最终目标是做任何事情,如果你需要时间戳 - 时间戳表示我会认为你可以改变UDF以便将它存储为这样