разбирать даты из нескольких столбцов с NA и датами, скрытыми в тексте - PullRequest
0 голосов
/ 30 октября 2019

У меня есть data.frame с датами, распределенными по столбцам и в грязном формате: столбец year содержит годы и NA с, столбец date_old содержит формат Month DD или DD (илидлительность даты) или NA s, а столбец hidden_date содержит текст и даты либо в формате .... YYYY ...., либо в формате .... DD Month YYYY .... (.... представляет общий текст переменной длины).

Пример data.frame выглядит следующим образом:

df <- data.frame(year = c("1992", "1993", "1995", NA),
                 date_old = c("February 15", "October 02-24", "15", NA),
                 hidden_date = c(NA, NA, "The hidden date is 15 July 1995", "The hidden date is 2005"))

Я хочу получить даты в формате YYYY-MM-DD (взять продолжительность первого дня дат) и заполнить неизвестные значения нулями.

Использование parse_date_time мне пока не помогло, и ожидаемый результат будет:

  year      date_old                     hidden_date        date
1 1992   February 15                            <NA>  1992-02-15
2 1993 October 02-24                            <NA>  1993-10-02
3 1995            15 The hidden date is 15 July 1995  1995-07-15
4 <NA>          <NA>         The hidden date is 2005  2005-00-00

Как мне лучше всего это сделать?

1 Ответ

4 голосов
/ 30 октября 2019

Это немного сложно, потому что у вас есть куча информации о дате в разных столбцах, которые вам нужно извлечь и объединить. Я не совсем понимаю, если у вас только есть три столбца, или если их может быть больше, поэтому я попытался решить общий случай произвольного числа столбцов. Если у вас есть только три столбца, каждый из которых всегда имеет одинаковый формат, то все может быть немного проще, но не намного.

Я бы начал с создания шаблона регулярных выражений за месяцИмена:

# We'll use dplyr, stringr, tidyr, readr, and purrr
library(tidyverse)

# We'll use month names and abbreviations just in case.
ms <- paste(c(month.name, month.abb), collapse = "|")

# [1] "January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"

Затем мы можем выполнить итерацию по каждому столбцу, извлекая год, месяц и день из каждой строки в виде фрейма данных, который затем объединяем в один фрейм данных. Цифровые суффиксы соответствуют исходным столбцам:

df_split_ymd <- map_dfc(df,
                        ~ map_dfr(
                            .,
                            ~ tibble(
                                year = str_extract(., "\\b\\d{4}\\b"),
                                month = str_extract(., str_glue("\\b({ms})\\b")),
                                day = str_extract(., "\\b\\d{2}\\b")
                                )
                            )
                        )

#### OUTPUT ####

# A tibble: 4 x 9
  year  month day   year1 month1   day1  year2 month2 day2 
  <chr> <chr> <chr> <chr> <chr>    <chr> <chr> <chr>  <chr>
1 1992  NA    NA    NA    February 15    NA    NA     NA   
2 1993  NA    NA    NA    October  02    NA    NA     NA   
3 1995  NA    NA    NA    NA       15    1995  July   15   
4 NA    NA    NA    NA    NA       NA    2005  NA     NA   

Наконец, столбцы year*, month* и day* должны быть coalesce d, а затем unite d, чтобы упростить анализ,Обратите внимание, что я заменил NA значения в day на «01», а значения в month на «Январь», потому что даты не могут содержать «00»:

df_ymd <- df_split_ymd %>% 
    mutate(year = coalesce(!!!as.list(select(., starts_with("year")))),
           month = coalesce(!!!as.list(select(., starts_with("month")))) %>% 
               replace_na("January"),
           day = coalesce(!!!as.list(select(., starts_with("day")))) %>% 
               replace_na("01")
           ) %>% 
    unite(ymd, year, month, day, sep = " ") %>% 
    select(ymd) %>% 
    mutate(ymd = parse_date(ymd, "%Y %B %d"))

#### OUTPUT ####

# A tibble: 4 x 1
  ymd       
  <date>    
1 1992-02-15
2 1993-10-02
3 1995-07-15
4 2005-01-01
...