San*_*San 0 csv r parquet apache-arrow
假设有一个csv
文件名为ta_sample.csv
:
"BILL_DT","AMOUNT"
"2015-07-27T18:30:00Z",16000
"2015-07-07T18:30:00Z",6110
"2015-07-26T18:30:00Z",250
"2015-07-22T18:30:00Z",1000
"2015-07-06T18:30:00Z",2640000
Run Code Online (Sandbox Code Playgroud)
read_csv_arrow
使用并自定义实际生产数据中始终需要的列类型来阅读上述内容:
library(arrow)
read_csv_arrow(
"ta_sample.csv",
col_names = c("BILL_DT", "AMOUNT"),
col_types = "td",
skip = 1,
timestamp_parsers = c("%Y-%m-%dT%H:%M:%SZ"))
Run Code Online (Sandbox Code Playgroud)
结果如下:
# A tibble: 5 x 2
BILL_DT AMOUNT
<dttm> <dbl>
1 2015-07-28 00:00:00 16000
2 2015-07-08 00:00:00 6110
3 2015-07-27 00:00:00 250
4 2015-07-23 00:00:00 1000
5 2015-07-07 00:00:00 2640000
Run Code Online (Sandbox Code Playgroud)
这里的问题是日期增加一天并且时间消失。这里值得一提的是,data.table::fread()
以及readr::read_csv()
正确阅读它,例如,
library(readr)
read_csv("ta_sample.csv")
# A tibble: 5 x 2
BILL_DT AMOUNT
<dttm> <dbl>
1 2015-07-27 18:30:00 16000
2 2015-07-07 18:30:00 6110
3 2015-07-26 18:30:00 250
4 2015-07-22 18:30:00 1000
5 2015-07-06 18:30:00 2640000
Run Code Online (Sandbox Code Playgroud)
BILL_DT
解析列中的示例值strptime
也可以完美地工作,如下所示:
strptime(c("2015-07-27T18:30:00Z", "2015-07-07T18:30:00Z"), "%Y-%m-%dT%H:%M:%SZ")
[1] "2015-07-27 18:30:00 IST" "2015-07-07 18:30:00 IST"
Run Code Online (Sandbox Code Playgroud)
需要调整哪些参数read_csv_arrow
才能获得与 给出的结果相同的结果readr::read_csv()
?
这里发生了一些事情,但它们都与时区以及 R + Arrow + 其他包的各个部分如何解释它们有关。
\n当 Arrow 读取时间戳时,它会将这些值视为 UTC。Arrow 尚无法在解析 [1] 时指定替代时区,因此将这些值存储为无时区(并假定 UTC)。尽管在这种情况下,由于您拥有的时间戳是 UTC(根据 ISO_8601,Z
末尾的 表示 UTC),它们会作为无时区 UTC 时间戳正确存储在 Arrow 中。时间戳的值是相同的(即,它们表示相同的 UTC 时间),不同之处在于它们的显示方式:它们是显示为 UTC 时间还是显示为本地时区。
当时间戳转换为 R 时,时区性被保留:
\n> from_arrow <- read_csv_arrow(\n+ "ta_sample.csv",\n+ col_names = c("BILL_DT", "AMOUNT"),\n+ col_types = "td",\n+ skip = 1,\n+ timestamp_parsers = c("%Y-%m-%dT%H:%M:%SZ"))\n> \n> attr(from_arrow$BILL_DT, "tzone")\nNULL\n
Run Code Online (Sandbox Code Playgroud)\nR 默认显示没有tzone
本地时区属性的时间戳(对我来说它当前是 CDT,对你来说它看起来像是 IST)。并且请注意,具有明确时区的时间戳会显示在该时区中。
> from_arrow$BILL_DT\n[1] "2015-07-27 13:30:00 CDT" "2015-07-07 13:30:00 CDT"\n[3] "2015-07-26 13:30:00 CDT" "2015-07-22 13:30:00 CDT"\n[5] "2015-07-06 13:30:00 CDT"\n
Run Code Online (Sandbox Code Playgroud)\n如果您想显示 UTC 时间戳,您可以执行以下操作:
\ntzone
属性(或者您可以用于lubridate::with_tz()
相同的操作):> attr(from_arrow$BILL_DT, "tzone") <- "UTC"\n> from_arrow$BILL_DT\n[1] "2015-07-27 18:30:00 UTC" "2015-07-07 18:30:00 UTC"\n[3] "2015-07-26 18:30:00 UTC" "2015-07-22 18:30:00 UTC"\n[5] "2015-07-06 18:30:00 UTC"\n
Run Code Online (Sandbox Code Playgroud)\ntzone
这里仍然未设置该属性,但显示的是 UTC,因为会话时区设置为 UTC)> Sys.setenv(TZ="UTC")\n> from_arrow <- read_csv_arrow(\n 3. "ta_sample.csv",\n 4. col_names = c("BILL_DT", "AMOUNT"),\n 5. col_types = "td",\n 6. skip = 1,\n 7. timestamp_parsers = c("%Y-%m-%dT%H:%M:%SZ"))\n> from_arrow$BILL_DT\n[1] "2015-07-27 18:30:00 UTC" "2015-07-07 18:30:00 UTC"\n[3] "2015-07-26 18:30:00 UTC" "2015-07-22 18:30:00 UTC"\n[5] "2015-07-06 18:30:00 UTC"\n> attr(from_arrow$BILL_DT, "tzone")\nNULL\n
Run Code Online (Sandbox Code Playgroud)\ncollect()
。这个 csv -> Arrow table -> data.frame 是在幕后发生的,因此这里没有进行其他转换(除了转换)。如果您正在应用其他转换,那么在 Arrow 表上执行操作可能会很有用且更高效,尽管它比前两个需要更多代码。> library(arrow)\n> library(dplyr)\n> tab <- read_csv_arrow(\n+ "ta_sample.csv",\n+ col_names = c("BILL_DT", "AMOUNT"),\n+ col_types = "td",\n+ skip = 1,\n+ as_data_frame = FALSE)\n> \n> tab_df <- tab %>% \n+ mutate(BILL_DT_cast = cast(BILL_DT, timestamp(unit = "s", timezone = "UTC"))) %>%\n+ collect()\n> attr(tab_df$BILL_DT, "tzone")\nNULL\n> attr(tab_df$BILL_DT_cast, "tzone")\n[1] "UTC"\n> tab_df\n# A tibble: 5 \xc3\x97 3\n BILL_DT AMOUNT BILL_DT_cast \n <dttm> <dbl> <dttm> \n1 2015-07-27 13:30:00 16000 2015-07-27 18:30:00\n2 2015-07-07 13:30:00 6110 2015-07-07 18:30:00\n3 2015-07-26 13:30:00 250 2015-07-26 18:30:00\n4 2015-07-22 13:30:00 1000 2015-07-22 18:30:00\n5 2015-07-06 13:30:00 2640000 2015-07-06 18:30:00\n
Run Code Online (Sandbox Code Playgroud)\n这也让人更加困惑,因为基本 Rstrptime()
不解析时区(这就是为什么你看到相同的时钟时间,但在上面的示例中使用 IST)。lubridate\'s[2] 解析函数确实尊重这一点,您可以在这里看到区别:
> lubridate::parse_date_time(c("2015-07-27T18:30:00Z", "2015-07-07T18:30:00Z"), "YmdHMS")\n[1] "2015-07-27 18:30:00 UTC" "2015-07-07 18:30:00 UTC"\n
Run Code Online (Sandbox Code Playgroud)\n[1] 虽然我们有两个与添加此功能相关的问题https://issues.apache.org/jira/browse/ARROW-12820和https://issues.apache.org/jira/browse/ARROW-13348
\n[2] 而且,lubridate 的文档甚至提到了这一点:
\n\n\nISO8601 与 UTC 的小时和分钟偏移量。例如 -0800、-08:00 或 -08,均表示比 UTC 晚 8 小时。此格式还与 Z (Zulu) UTC 指示器匹配。因为 base::strptime() 不完全支持 ISO8601,所以该格式被实现为 4 个指令的并集:Ou (Z)、Oz (-0800)、OO (-08:00) 和 Oo (-08)。您可以像使用其他命令一样使用这四个命令,但很少有必要。parse_date_time2() 和 fast_strptime() 支持所有时区格式。\n https://lubridate.tidyverse.org/reference/parse_date_time.html
\n