在R中排列日期字符

arrange date characters in R

我正在处理许多 csv 文件,这些文件在括号中标有年份。例如:

files_names <- list.files("data/", recursive = TRUE, full.names = TRUE)

[1] "data/BOC_All_ATMImage_(Aug 2020).txt" "data/BOC_All_ATMImage_(Aug 2021).txt"
[3] "data/BOC_All_ATMImage_(Feb 2021).txt" "data/BOC_All_ATMImage_(Feb_2020).txt"
[5] "data/BOC_All_ATMImage_(May 2021).txt" "data/BOC_All_ATMImage_(Nov 2019).txt"

column_names <- files_names %>%
  str_extract(., "(?<=\().*?(?=\))") %>%
  str_to_lower() %>%
  str_replace(., " ", "_")

"aug_2020" "aug_2021" "feb_2021" "feb_2020" "may_2021" "nov_2019"

我在 purrr 中使用 map2 函数来处理 csv 文件,并在循环中使用 files_namescolumn_names 设置列名。

data <-
  map2(files_names, column_names,
       ~ read_csv(.x, guess_max = 50000) %>%
         mutate(
           day = 01,
           month_year = str_extract(.x, "(?<=\().*?(?=\))"),
           date_dmy = paste0(day, "-", month_year),
           date = dmy(date_dmy),
           "{.y}" := 1
         ),
       .id = "group" 
  )

我需要弄清楚如何排列此列表,以便每个数据集按时间顺序排列。一种方法是在将初始字符向量(files_namescolumn_names)送入循环之前排列它们。或者简单地排列 data 列表以便数据帧按时间顺序排列可能会更容易?我在每个数据框中创建了一个 date 变量,所以这可能是另一种方法,但我不确定如何按日期变量对列表重新排序。

我们可以使用str_match来搜索月份和年份。之后,使用一些 dplyr 来清理数据。为了安排月份我想到了使用一个因素。

library(tidyverse)

files_names <-
  c(
    "data/BOC_All_ATMImage_(Aug 2020).txt", "data/BOC_All_ATMImage_(Aug 2021).txt",
    "data/BOC_All_ATMImage_(Feb 2021).txt", "data/BOC_All_ATMImage_(Feb_2020).txt",
    "data/BOC_All_ATMImage_(May 2021).txt", "data/BOC_All_ATMImage_(Nov 2019).txt"
  )

factor_w_month <- partial(factor, levels = )
months <- partial(factor, levels = (c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")))

files_names %>%
  str_match(".*_\((.*)[ _](\d+)\)\.txt$") %>%
    as.data.frame() %>%
    mutate(V2 = months(V2)) %>%
    arrange(V3, V2) %>% 
    transmute(files_names = V1, column_names = str_to_lower(str_c(V2, '_', V3)))
#>                            files_names column_names
#> 1 data/BOC_All_ATMImage_(Nov 2019).txt     nov_2019
#> 2 data/BOC_All_ATMImage_(Feb_2020).txt     feb_2020
#> 3 data/BOC_All_ATMImage_(Aug 2020).txt     aug_2020
#> 4 data/BOC_All_ATMImage_(Feb 2021).txt     feb_2021
#> 5 data/BOC_All_ATMImage_(May 2021).txt     may_2021
#> 6 data/BOC_All_ATMImage_(Aug 2021).txt     aug_2021

reprex package (v2.0.1)

于 2021-12-20 创建

我认为以下解决方案也可以帮助您在开始将日期读入 R 之前对日期进行排序:

library(dplyr)
library(stringr)

files_names %>%
  enframe() %>%
  mutate(date = str_extract(value, "(?<=\().*(?=\))"), 
         date = paste(str_extract(date, "\d+"), str_extract(date, "[[:alpha:]]+"), "01", 
                      sep = "-"), 
         date = as.Date(date, format = "%Y-%b-%d")) %>%
  arrange(desc(date))

# A tibble: 6 x 3
   name value                                date      
  <int> <chr>                                <date>    
1     2 data/BOC_All_ATMImage_(Aug 2021).txt 2021-08-01
2     5 data/BOC_All_ATMImage_(May 2021).txt 2021-05-01
3     3 data/BOC_All_ATMImage_(Feb 2021).txt 2021-02-01
4     1 data/BOC_All_ATMImage_(Aug 2020).txt 2020-08-01
5     4 data/BOC_All_ATMImage_(Feb_2020).txt 2020-02-01
6     6 data/BOC_All_ATMImage_(Nov 2019).txt 2019-11-01

关于您使用的正则表达式的一些小提示,我认为您不需要使 .* 部分变得懒惰。

通过从 column_names 解析和排序日期,您可以按时间顺序排列 files_names 并从那里处理您的文件

files_names <- list.files("data/", recursive = TRUE, full.names = TRUE)

column_names <- files_names %>%
  str_extract(., "(?<=\().*?(?=\))") %>%
  str_to_lower() %>%
  str_replace(., " ", "_")


files_names <- files_names[
order(readr::parse_date(column_names,"%b_%Y"))]
files_names
[1] "data/BOC_All_ATMImage_(Nov 2019).txt"
[2] "data/BOC_All_ATMImage_(Feb_2020).txt"
[3] "data/BOC_All_ATMImage_(Aug 2020).txt"
[4] "data/BOC_All_ATMImage_(Feb 2021).txt"
[5] "data/BOC_All_ATMImage_(May 2021).txt"
[6] "data/BOC_All_ATMImage_(Aug 2021).txt"

如果没有 csv 文件,我真的无法 运行 你的代码,但看起来你已经有了一个 tibbles 列表,并且你已经使用来自文档名称。在这种情况下,你只需要

data %>% bind_rows() %>% arrange(date)

获取单个标题,但行根据文件名中的日期排序。