使用 R 从 excel sheet 读取时如何检测时间
How to detect TIME when reading from an excel sheet using R
问题是,当我使用 openxlsx
包中的 read.xlsx
从 excel sheet 读取到 R 时,TIME
列被转换为一小部分。
这是一个例子,
dfin <-
DATE TIME
15/02/2015 8:00 AM
22/01/2014 10:00 PM
library(openxlsx)
test <- read.xlsx("dfin.xlsx", sheet = 1,
detectDates=TRUE, skipEmptyRows = TRUE,
skipEmptyCols = TRUE, rows = NULL, cols = NULL, check.names = FALSE,
namedRegion = NULL, na.strings = "NA", fillMergedCells = FALSE)
输出:
DATE TIME
2015-02-15 0.3333333
2014-01-22 0.9166667
我不确定为什么会这样,也不知道是否有办法解决这个问题,因为我需要同时使用 DATE 和 TIME 来进行一些计算。
R 确实没有时间格式,所以我建议使用 read_excel
阅读它,它会自动检测列类型。这会将其转换为具有随机日期的日期时间格式,然后您可以将其删除,然后再将其转换为正确的时间戳。
library(readxl)
library(lubridate)
test <- read_excel('dfin.xlsx',trim_ws = TRUE) %>%
#return the TIME column to the way it is written in Excel
mutate(TIME = as.character(gsub(".* ","",TIME)),
#format the date column
DATE = dmy(DATE),
#turn it into a timestamp
TIMESTAMP = as.POSIXct(paste(DATE,TIME)))
我的第一个猜测是 read.xlsx()
在读取文件时试图猜测 .xlsx 中的日期外观列,并奇怪地将时间从 %I:%M %p
格式转换为 24 小时的分数(因为例如 0.3333333 * 24 = 7.999999
which is exactly 8.0)。但后来我注意到,如果我将参数 detectDates
更改为 FALSE
什么都没有真正改变 - 它输出相同的数据帧。所以它什么也没猜,它只是按原样读取 TIME
。
如果您尝试在 Excel 工作簿中编辑 10:00 PM
,您会发现它实际上存储为 22:00:00
。那么为什么最后它表示为 24
的分数?!不知道,希望有大佬解释一下。
@Randall 方法与 openxlsx::read.xlsx()
相比是非常好的替代方法。请注意,read_xlsx()
将 TIME
识别为 %H:%M:%S
,并将其转换为虚拟 POSIXct/POSIXt
对象,即 1899-12-31 08:00:00
和 1899-12-31 22:00:00
.
令人惊讶的是,read_xlsx()
无法识别 DATE
具有 %d-%m-%Y
格式,并将其解释为 character
。这意味着我们需要将两个变量转换为适当的格式以获得所需的输出。
我认为我们不需要使用 gsub
从 POSIXct
对象获取 12 小时时钟时间,为此目的使用 format
更容易。将 DATE
从 %d-%m-%Y
格式转换为 %Y-%m-%d
格式甚至更容易:
library(dplyr)
library(readxl)
read_xlsx("myfile.xlsx") |>
mutate(
DATE = as.Date(DATE, "%d/%m/%Y"),
TIME = format(TIME, "%I:%M %p") # “That’s what I do: I drink and I know things.”
)
产生:
# A tibble: 2 x 2
DATE TIME
<date> <chr>
1 2015-02-15 08:00 AM
2 2014-01-22 10:00 PM
我遇到了同样的问题并按如下方式解决了 - 快速而肮脏:
使用readxl:read_excel()
读取数据。
不失一般性,我们只考虑从 "0.72222222222222"
获取 17:20
而不是包含时间数据的列。请注意从 excel 文件中读取的值可能有不需要的类型,但对于计算我们需要数字。
x <- as.numeric("0.72222222222222")*24
minutes <- round((x %% 1)*60, digits = 0)
hours <- round(x - minutes/60, digits = 0)
if (minutes < 10){ #if minutes is a single digit need to insert a preceding 0
minutes= paste0("0",minutes)
}
paste0(hours, ":", minutes)
#17:20
读取时间值作为“日期”:
test <- read_excel('dfin.xlsx', col_types = c("date"), ...)
然后trim用substr()
得到时间:
test <- substr(test,12,16)
问题是,当我使用 openxlsx
包中的 read.xlsx
从 excel sheet 读取到 R 时,TIME
列被转换为一小部分。
这是一个例子,
dfin <-
DATE TIME
15/02/2015 8:00 AM
22/01/2014 10:00 PM
library(openxlsx)
test <- read.xlsx("dfin.xlsx", sheet = 1,
detectDates=TRUE, skipEmptyRows = TRUE,
skipEmptyCols = TRUE, rows = NULL, cols = NULL, check.names = FALSE,
namedRegion = NULL, na.strings = "NA", fillMergedCells = FALSE)
输出:
DATE TIME
2015-02-15 0.3333333
2014-01-22 0.9166667
我不确定为什么会这样,也不知道是否有办法解决这个问题,因为我需要同时使用 DATE 和 TIME 来进行一些计算。
R 确实没有时间格式,所以我建议使用 read_excel
阅读它,它会自动检测列类型。这会将其转换为具有随机日期的日期时间格式,然后您可以将其删除,然后再将其转换为正确的时间戳。
library(readxl)
library(lubridate)
test <- read_excel('dfin.xlsx',trim_ws = TRUE) %>%
#return the TIME column to the way it is written in Excel
mutate(TIME = as.character(gsub(".* ","",TIME)),
#format the date column
DATE = dmy(DATE),
#turn it into a timestamp
TIMESTAMP = as.POSIXct(paste(DATE,TIME)))
我的第一个猜测是 read.xlsx()
在读取文件时试图猜测 .xlsx 中的日期外观列,并奇怪地将时间从 %I:%M %p
格式转换为 24 小时的分数(因为例如 0.3333333 * 24 = 7.999999
which is exactly 8.0)。但后来我注意到,如果我将参数 detectDates
更改为 FALSE
什么都没有真正改变 - 它输出相同的数据帧。所以它什么也没猜,它只是按原样读取 TIME
。
如果您尝试在 Excel 工作簿中编辑 10:00 PM
,您会发现它实际上存储为 22:00:00
。那么为什么最后它表示为 24
的分数?!不知道,希望有大佬解释一下。
@Randall 方法与 openxlsx::read.xlsx()
相比是非常好的替代方法。请注意,read_xlsx()
将 TIME
识别为 %H:%M:%S
,并将其转换为虚拟 POSIXct/POSIXt
对象,即 1899-12-31 08:00:00
和 1899-12-31 22:00:00
.
令人惊讶的是,read_xlsx()
无法识别 DATE
具有 %d-%m-%Y
格式,并将其解释为 character
。这意味着我们需要将两个变量转换为适当的格式以获得所需的输出。
我认为我们不需要使用 gsub
从 POSIXct
对象获取 12 小时时钟时间,为此目的使用 format
更容易。将 DATE
从 %d-%m-%Y
格式转换为 %Y-%m-%d
格式甚至更容易:
library(dplyr)
library(readxl)
read_xlsx("myfile.xlsx") |>
mutate(
DATE = as.Date(DATE, "%d/%m/%Y"),
TIME = format(TIME, "%I:%M %p") # “That’s what I do: I drink and I know things.”
)
产生:
# A tibble: 2 x 2
DATE TIME
<date> <chr>
1 2015-02-15 08:00 AM
2 2014-01-22 10:00 PM
我遇到了同样的问题并按如下方式解决了 - 快速而肮脏:
使用
readxl:read_excel()
读取数据。不失一般性,我们只考虑从
"0.72222222222222"
获取17:20
而不是包含时间数据的列。请注意从 excel 文件中读取的值可能有不需要的类型,但对于计算我们需要数字。
x <- as.numeric("0.72222222222222")*24
minutes <- round((x %% 1)*60, digits = 0)
hours <- round(x - minutes/60, digits = 0)
if (minutes < 10){ #if minutes is a single digit need to insert a preceding 0
minutes= paste0("0",minutes)
}
paste0(hours, ":", minutes)
#17:20
读取时间值作为“日期”:
test <- read_excel('dfin.xlsx', col_types = c("date"), ...)
然后trim用
substr()
得到时间:test <- substr(test,12,16)