我正在嘗試從文本中提取日期并在資料集中創建一個新列。在 A1 列中以不同格式輸入日期(mm-dd-yy 或 mm-dd)。我需要找到一種方法來識別 A1 列中的日期,然后在缺少年份時添加年份。到目前為止,無論格式如何,我都能夠提取日期;但是,當我在新列 A2 上使用 as.Date 時,mm-dd 格式的日期變為<NA>. 我知道對于這種情況可能沒有直接的解決方案,但是解決方法(可推廣到更大的資料集)會很棒。這一年將從 2019 年 9 月到 2020 年 8 月。此外,我不確定為什么我在as.Date函式無法控制日期的顯示方式。后一個問題不是那么重要,但我對 R 函式的行為感到驚訝。tidyverse 中的解決方案將不勝感激。
library(tidyverse)
library(stringr)
db <- data.frame(A1 = c("review 11/18", "begins 12/4/19", "3/5/20", NA, "deadline 09/5/19", "9/3"))
db %>% mutate(A2 = str_extract(A1, "[0-9/0-9] "))
# A1 A2
#1 review 11/18 11/18
#2 begins 12/4/19 12/4/19
#3 3/5/20 3/5/20
#4 <NA> <NA>
#5 deadline 09/5/19 09/5/19
#6 9/3 9/3
db %>% mutate(A2 = str_extract(A1, "[0-9/0-9] ")) %>%
mutate(A2 = A2 %>% as.Date(., "%m/%d/%y"))
# A1 A2
# 1 review 11/18 <NA>
# 2 begins 12/4/19 2019-12-04
# 3 3/5/20 2020-03-05
# 4 <NA> <NA>
# 5 deadline 09/5/19 2019-09-05
# 6 9/3 <NA>
uj5u.com熱心網友回復:
也許:
library(tidyverse)
db <- data.frame(A1 = c("review 11/18", "begins 12/4/19", "3/5/20", NA, "deadline 09/5/19", "9/3"))
#year from september to august 2019
(db <-
db %>%
mutate(A2 = str_extract(A1, '[\\d\\d/] '),
A2 = if_else(str_count(A2, '/') == 1 & as.numeric(str_extract(A2, '\\d ')) > 8, paste0(A2, '/19'), A2),
A2 = if_else(str_count(A2, '/') == 1 & as.numeric(str_extract(A2, '\\d ')) <= 8, paste0(A2, '/20'), A2),
A2 = as.Date(A2, "%m/%d/%y")) )
#> A1 A2
#> 1 review 11/18 2019-11-18
#> 2 begins 12/4/19 2019-12-04
#> 3 3/5/20 2020-03-05
#> 4 <NA> <NA>
#> 5 deadline 09/5/19 2019-09-05
#> 6 9/3 2019-09-03
由reprex 包(v2.0.1)于 2021 年 11 月 21 日創建
uj5u.com熱心網友回復:
嗯,這既不是一個漂亮、簡潔或整潔的解決方案,但它確實有效,并且在其模塊化方面應該是靈活的。
library(tidyverse)
db <- data.frame(A1 = c("review 11/18", "begins 12/4/19", "3/5/20", NA, "deadline 09/5/19", "9/3"))
db <- db %>% mutate(A2 = str_extract(A1, "[0-9/0-9] "), A2 = str_extract(A1, "[0-9/0-9] "))
test1 <- unlist(lapply(str_split(db$A2, "/", n = 3), function(x) length(x)))
test2 <- lapply(str_split(db$A2, "/", n = 3), function(x) as.numeric(x))
if(test1 == 2){
if(test2[[1]] >= 9){
db$A2 <- ifelse(test = between(nchar(db$A2), 3, 5) & !is.na(db$A2), yes = paste0(db$A2, "/19"), no = db$A2)
}
if(test2[[1]] < 9){
db$A2 <- ifelse(test = between(nchar(db$A2), 3, 5) & !is.na(db$A2), yes = paste0(db$A2, "/20"), no = db$A2)
}
}
db <- db %>% mutate(A2 = A2 %>% as.Date(., "%m/%d/%y"))
db
A1 A2
1 review 11/18 2019-11-18
2 begins 12/4/19 2019-12-04
3 3/5/20 2020-03-05
4 <NA> <NA>
5 deadline 09/5/19 2019-09-05
6 9/3 2019-09-03
uj5u.com熱心網友回復:
我喜歡用于許多正則運算式場景的rematch2包。
第一個模式嘗試匹配完整的 m/d/y 值。第二個模式試圖匹配部分 m/d 值(此外,它將月份與日期分開,因此它可以確定它應該是 2019 年還是 2020 年)。
一旦這些部分被隔離,剩下的就是一系列的小步驟。
db |>
rematch2::bind_re_match(from = A1, "^.*?(?<mdy>\\d{1,2}/\\d{1,2}/\\d{2})$") |>
rematch2::bind_re_match(from = A1, "^.*?(?<md_m>\\d{1,2})/(?<md_d>\\d{1,2})$") |>
dplyr::mutate(
md_m = as.integer(md_m),
md_y = dplyr::if_else(9L <= md_m, "19", "20"), # It's 2019 if the month is Sept or later
md = sprintf("%i/%s/%s", md_m, md_d, md_y), # Assemble components
md = as.Date(md , "%m/%d/%y"), # Convert data type
mdy = as.Date(mdy, "%m/%d/%y"), # Convert data type
date = dplyr::coalesce(mdy, md), # Prefer the mdy if it's not missing
)
輸出:
A1 mdy md_m md_d md_y md date
1 review 11/18 <NA> 11 18 19 2019-11-18 2019-11-18
2 begins 12/4/19 2019-12-04 4 19 20 2020-04-19 2019-12-04
3 3/5/20 2020-03-05 5 20 20 2020-05-20 2020-03-05
4 <NA> <NA> NA <NA> <NA> <NA> <NA>
5 deadline 09/5/19 2019-09-05 5 19 20 2020-05-19 2019-09-05
6 9/3 <NA> 9 3 19 2019-09-03 2019-09-03
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/362335.html
上一篇:路徑驗證-嘗試修改我的RegEx,使其僅匹配包含檔案名和擴展名的路徑
下一篇:蟒蛇僅用時間替換日期和時間字串
