1 CHƯƠNG I Giới thiệu

1.1 Đặt vấn đề

R là một ngôn ngữ lập trình hoàn thiện định hướng cho tính toán thống kê, phân tích dữ liệu. Nó cho phép bạn xây dựng những hàm, những câu lệnh chỉ để giải quyết một nhóm các nhiệm vụ phân tích đặc thù nào đó và chia sẻ chúng trên mạng. Chẳng hạn, nếu có một kiểm định mới, một mô hình mới về phương diện lý thuyết và được đăng trên một tạp chí chuyên nghành nào đó, bạn hoàn toàn có thể viết một chương trình nhằm biến kiểm định mới, những mô hình mới chỉ ở dạng lý thuyết kia thành một hàm cụ thể trong R. Nếu được kiểm tra bởi cộng đồng những người sử dụng rằng đúng và không có lỗi, hàm mà bạn viết sẽ được thừa nhận và sử dụng rộng rãi.

Viết một hàm cụ thể trong R là một điều phổ biến, nó phụ thuộc vào nhu cầu làm việc của người sử dụng. Và người viết có thể trình bày và thao tác theo ý của mình sau đó đăng lên sử dụng rộng rãi, ai cũng có thể sử dụng. Vấn đề của người sử dụng là làm sao để hiểu nguyên lý làm việc của một gói và sử dụng nó vào mục đích nghiên cứu của cá nhân họ.

R là một phần mềm đồi hỏi sự tỉ mỉ và chính xác. Nó có chút khắt khe hơn khi yêu cầu hai thứ: (1) sự thận trọng trong việc gõ các câu lệnh, và (2) tuần tự từng bước.

Môi trường làm việc trong R khắt khe về thao tác các lệnh. Không những thế nó còn nhọc nhằn hơn nếu bạn làm việc với ngày và giờ trong R. Thoạt nhìn, ngày và giờ có vẻ đơn giản. Chúng ta có thể sử dụng chúng mọi lúc trong cuộc sống hằng ngày của mình và dường như chúng không gây ra nhiều nhầm lẫn. Tuy nhiên, khi chúng ta càng tìm hiểu về ngày tháng và thời gian, chúng càng trở nên phức tạp. Để cho thấy nó khó nhằn, bạn hãy thử trả lời ba câu hỏi có vẻ đơn giản sau:

  • Có phải mỗi năm có 365 ngày không?

  • Có phải mỗi ngày đều có 24 giờ không?

  • Có phải mỗi phút có 60 giây không?

Chúng ta biết rằng không phải năm nào cũng có 365 ngày, nhưng bạn có biết quy tắc để xác định xem năm nào có năm nhuận hay không? Hơn thế ở một số nơi trên thế giới sử dụng giờ mùa hè (DST), do đó có một số ngày có 23 giờ và những ngày khác có 25 giờ. Và có thể bạn cũng không biết rằng một số phút có 61 giây thay vì 60 giây vì cứ sau một vài giây nhuận lại được thêm vào vì vòng quay của Trái Đất đang dần chậm lại. Ngày và giờ rất khó để xác định vì chúng phải dung hòa hai hiện tượng vật lý (sự quay của Trái đất và quỹ đạo của nó quanh mặt trời) với toàn bộ các hiện tượng địa chính trị bao gồm tháng, múi, giờ và DST.

1.2 Giới thiệu về packages “lubridate”

1.2.1 Nguồn gốc

Gói lubridate được phát triển và được duy trì bởi Hadley Wickham và các đồng nghiệp của ông. Hadley Wickham là một trong những nhà phát triển hàng đầu trong cộng đồng R và đã tạo ra nhiều gói phổ biến khác như ggplot2 và dplyr.

Lubridate ban đầu được phát triển vào năm 2011 để làm việc với ngày tháng và thời gian trong R một cách thuận tiện hơn. Hadley Wickham và Garrett Grolemund là hai nhà phát triển chính trong quá trình tạo ra gói lubridate, và sau đó nó đã được mở rộng và nâng cấp bởi cộng đồng R để trở thành một công cụ rất hữu ích cho việc làm việc với ngày tháng và thời gian.

Lubridate là một gói mở nguồn (open-source) và được phân phối dưới giấy phép GPL-2, cho phép mọi người sử dụng, sao chép, phân phối và thay đổi gói này theo các điều khoản của giấy phép.

Ngày nay, lubridate là một trong những gói phổ biến nhất để làm việc với ngày tháng và thời gian trong R và đã được sử dụng rộng rãi trong cộng đồng phân tích dữ liệu và khoa học dữ liệu.

1.2.2 Tổng quan về packages lubridate

Gói lubridate trong R là một công cụ mạnh mẽ và tiện lợi để làm việc với ngày tháng và thời gian. Nó cung cấp các hàm và phương pháp để phân tích cú pháp ngày tháng, tính toán với ngày tháng, và định dạng ngày tháng theo yêu cầu của bạn.

Các tính năng chính của lubridate bao gồm:

  1. Chuyển đổi và phân tích cú pháp ngày tháng: Lubridate cung cấp các hàm như ymd(), mdy(), và dmy() để chuyển đổi chuỗi thành đối tượng ngày tháng trong R. Nó cho phép bạn phân tích cú pháp ngày tháng từ các chuỗi đầu vào trong định dạng “năm-tháng-ngày”, “tháng-ngày-năm”, và “ngày-tháng-năm” một cách dễ dàng.

  2. Các hàm để lấy thông tin từ ngày tháng và thời gian: Lubridate cung cấp các hàm như year(), month(), day(), hour(), minute(), và second() để lấy thông tin về các thành phần của ngày tháng và thời gian. Bạn có thể sử dụng chúng để truy vấn và khai thác các thành phần này theo nhu cầu của mình.

  3. Tính toán và xử lý ngày tháng: Lubridate cho phép bạn thực hiện các phép tính với ngày tháng như cộng hoặc trừ các khoảng thời gian, tính toán hiệu giữa hai ngày tháng, tạo ra chuỗi thời gian liên quan đến một ngày tháng cụ thể, và nhiều hơn nữa. Điều này rất hữu ích khi bạn cần làm việc với các tính toán liên quan đến ngày tháng và thời gian.

  4. Định dạng ngày tháng và thời gian: Lubridate cung cấp các hàm để định dạng đối tượng ngày tháng và thời gian thành các chuỗi theo định dạng mong muốn. Bạn có thể sử dụng các hàm format() để định dạng ngày tháng và thời gian theo ý muốn.

  5. Xử lý múi giờ và múi giờ hè: Lubridate hỗ trợ xử lý thông tin về múi giờ và múi giờ hè (DST). Bạn có thể chuyển đổi giữa các múi giờ khác nhau và tính toán mà không bị ảnh hưởng bởi múi giờ hè.

  6. Trực quan hóa ngày tháng và thời gian: Lubridate tích hợp tốt với các gói trực quan hóa như ggplot2, giúp bạn trực quan hóa dữ liệu ngày tháng và thời gian một cách trực quan và dễ dàng.

Gói lubridate là một công cụ mạnh mẽ và linh hoạt để làm việc với ngày tháng và thời gian trong R. Nó cung cấp nhiều chức năng hữu ích và dễ sử dụng giúp bạn giải quyết các vấn đề liên quan đến ngày tháng và thời gian trong phân tích dữ liệu và khoa học dữ liệu.

1.3 Lý do chọn chủ đề

Ngày và giờ là một khía cạnh quan trọng của phân tích dữ liệu trong nhiều lĩnh vực và việc xử lý cũng như phân tích chính xác dữ liệu ngày giờ là điều cần thiết để có thể thu được kết quả đáng tin cậy hơn.

Dữ liệu ngày giờ có thể gây khó khăn khi làm việc. Ngày tháng có nhiều định dạng khác nhau, khiến việc nhận dạng và phân tích cú pháp chúng trở thành một thách thức. Chương trình của R có nhận ra định dạng ngày giờ mà chúng ta muốn hay không? Nếu không nhận dạng, chúng ta sẽ gặp phải các vấn đề cụ thể về thời gian. Làm thế nào chúng ta có thể dễ dàng trích xuất các thành phần của ngày giờ, chẳng hạn như năm, tháng hoặc giây? Làm cách nào chúng ta có thể chuyển đổi giữa các múi giờ hoặc so sánh thời gian từ những nơi sử dụng giờ mùa hè (DST) với thời gian từ những nơi không sử dụng? Ngày giờ thậm chí còn tạo ra nhiều phức tạp hơn khi chúng ta cố gắng thực hiện phép tính số học với chúng. Các quy ước như năm nhuận và DST khiến chúng ta không rõ ý nghĩa của từ “một ngày kể từ bây giờ” hay “chính xác là hai năm nữa”. Ngay cả những giây nhuận cũng có thể phá vỡ một phép tính có vẻ đơn giản. Sự phức tạp này cũng ảnh hưởng đến các tác vụ khác, chẳng hạn như xây dựng các dấu kiểm hợp lý để vẽ biểu đồ dữ liệu ngày giờ.

Trong khi cơ sở R (R Development Core Team 2011) xử lý một số vấn đề này, thì cú pháp mà nó sử dụng có thể khó hiểu và khó nhớ. Hơn nữa, code R chính xác thường thay đổi tùy thuộc vào loại đối tượng ngày giờ được sử dụng. “Lubridate” nhận diện phát hiện những vấn đề này và giúp làm việc với dữ liệu ngày-giờ trong R dễ dàng hơn. Nó cũng cung cấp các công cụ để thao tác với ngày-giờ theo những cách mới lạ nhưng hữu ích. Lubridate sẽ nâng cao trải nghiệm của người dùng cho bất kỳ phân tích nào bao gồm dữ liệu ngày giờ.

1.4 Mục tiêu chủ đề

Gói “lubridate” trong R là một gói phổ biến được sử dụng để làm việc với dữ liệu thời gian và ngày tháng. Mục tiêu chính của việc tìm hiểu gói “lubridate” là nắm vững cách sử dụng các hàm và công cụ của gói này để thực hiện các tác vụ liên quan đến xử lý dữ liệu thời gian và ngày tháng. Dưới đây là một số mục tiêu cụ thể để tìm hiểu gói “lubridate”:

  1. Chuyển đổi và xử lý dữ liệu thời gian:

    • Chuyển đổi chuỗi ký tự thành đối tượng thời gian.

    • Trích xuất thông tin về ngày, tháng, năm, giờ, phút, giây từ đối tượng thời gian.

    • Xử lý vấn đề về múi giờ (time zones), giờ mùa (daylight saving time) và thứ tự ngày tháng (date-time order).

    • Tính toán khoảng cách thời gian giữa hai ngày hay thời điểm.

    • Làm việc với chuỗi ký tự thời gian có định dạng không chuẩn.

  2. Xử lý và biến đổi dữ liệu ngày tháng:

    • Thay đổi định dạng của đối tượng ngày tháng.

    • Tạo ra đối tượng ngày, ví dụ như “hôm nay”, “tuần sau”, “tháng sau”.

    • Tính toán tuổi (age) và thời gian sống (lifespan) từ ngày sinh.

  3. Tính toán thời gian và chuẩn hóa:

    • Tính toán thời gian chạy chương trình (runtime) và thời gian chờ đợi (wait time).

    • Chuẩn hóa dữ liệu thời gian bằng cách làm mịn giá trị và định dạng.

    • Làm việc với chuỗi ký tự thời gian không đồng nhất.

  4. Trực quan hóa và biểu đồ hóa dữ liệu thời gian:

    • Tạo biểu đồ dữ liệu thời gian theo giai đoạn (time series).

    • Vẽ biểu đồ dạng line plot, bar plot, histogram và scatter plot dữ liệu thời gian.

    • Tạo biểu đồ dạng trend plot và seasonal plot để theo dõi xu hướng và mô hình của dữ liệu thời gian.

  5. Xử lý và tương tác với dữ liệu thời gian trong các tác vụ phân tích dữ liệu:

    • Lọc, chọn và tạo hạng mục (bins) dựa trên thời gian.

    • Gom nhóm và tính toán tổng kết các biến dựa trên thời gian.

    • Xử lý và phân tích dữ liệu thời gian trong khung dữ liệu (data frame) hoặc tập dữ liệu (dataset).

Mục tiêu của việc tìm hiểu gói “lubridate” là nắm vững các tính năng và công cụ để làm việc với dữ liệu thời gian và ngày tháng, từ việc biến đổi, xử lý cho đến phân tích và biểu đồ hóa. Điều này sẽ giúp bạn làm việc hiệu quả với các tác vụ liên quan đến dữ liệu có liên quan đến thời gian và ngày tháng trong R.

1.5 Đối tượng nghiên cứu

Trong gói lubridate, đối tượng nghiên cứu chính là ngày tháng và thời gian. Gói lubridate cung cấp các công cụ và chức năng để làm việc với đối tượng ngày tháng, giúp bạn phân tích, xử lý và tính toán các thông tin liên quan đến ngày tháng và thời gian.

Đối tượng ngày tháng trong lubridate được biểu diễn bằng đối tượng DateDateTime (hoặc POSIXct), tùy thuộc vào độ chính xác và yêu cầu của bạn.

1.6 Bố cục tiểu luận

Bên cạnh Danh mục tài liệu tham khảo và phụ lục, tiểu luận bao gồm 4 chương, với nội dung cụ thể như sau:

Chương 1: Giới thiệu. Chương này nhằm mục tiêu giới thiệu khái quát các nội dung chính của tiểu luận như tầm quan trọng của việc xử lý thời gian trong R, lý do chọn chủ đề, đối tượng nghiên cứu, và mục tiêu nghiên cứu cuối cùng là phần bố cục của tiểu luận.

Chương 2: Packages lubridate. Dựa vào các phân tích tổng hợp ở Chương 2, chương này sẽ trình bày tổng quan về lý thuyết các hàm, cách sử dụng, các tính toán được áp dụng trong package lubridate

Chương 3: Thực hành. Chương này nhằm mục đích ứng dụng package lubridate để phân tích trên một bộ dữ liệu thực tế

Chương 4: Kết luận. Chương cuối này, nói về những khó khăn mà trong quá trình tìm hiểu về package nhóm chúng em gặp phải. Bao gồm, những ưu nhược điểm mà package lubridate mang lại và những khó khăn trong quá trình nhóm em phân tích dữ liệu thời gian với packge này.

2 CHƯƠNG II Packages lubridate

2.1 Cơ sở lý luận

Ta luôn nói đến dữ liệu thời gian vậy dữ liệu thời gian là gì và nó có vai trò như thế nào trong phân tích dữ liệu?

Dữ liệu thời gian là dạng dữ liệu mà các quan sát được gắn kết với các thông tin về thời gian, bao gồm ngày, tháng, năm, giờ, phút và giây. Dữ liệu thời gian được sử dụng rộng rãi trong phân tích dữ liệu vì nó cung cấp thông tin về thứ tự và sự thay đổi theo thời gian của các sự kiện.

Dữ liệu thời gian có vai trò quan trọng trong phân tích dữ liệu vì nó cho phép chúng ta:

  1. Phân tích xu hướng và biến động theo thời gian: Dữ liệu thời gian cho phép chúng ta xem xét sự thay đổi theo thời gian của các biến và cung cấp thông tin về các xu hướng, chu kỳ và biến động trong dữ liệu.

  2. So sánh với nhau: Dữ liệu thời gian cho phép chúng ta so sánh sự thay đổi và sự tương quan giữa các biến trong cùng một thời gian hoặc giữa các khoảng thời gian khác nhau.

  3. Dự đoán và dự báo: Dữ liệu thời gian cung cấp cơ sở cho việc xây dựng và đánh giá các mô hình dự báo và dự đoán trong nhiều lĩnh vực như kinh tế, tài chính, khoa học xã hội và hậu cần.

  4. Phân tích chuỗi thời gian: Dữ liệu thời gian cung cấp cơ sở cho các phương pháp phân tích chuỗi thời gian như ARIMA (Autoregressive Integrated Moving Average), SARIMA(Seasonal ARIMA), và GARCH (Generalized Autoregressive Conditional Heteroscedasticity) để dự đoán và mô hình hóa các mô hình thay đổi theo thời gian.

Các phân tích dữ liệu thời gian giúp ta có cái nhìn rõ ràng và sâu sắc hơn về sự điều chỉnh và biến động theo thời gian trong dữ liệu, và từ đó giúp chúng ta hiểu và dự đoán các xu hướng, chu kỳ và sự biến động trong các quy trình và hiện tượng có thời gian.

2.2 Các định dạng ngày tháng trong R

Trong R, có nhiều định dạng khác nhau để biểu diễn ngày tháng. Dưới đây là một số định dạng phổ biến:

  1. Định dạng chuỗi ký tự (character format):

    • “YYYY-MM-DD” hoặc “YYYY/MM/DD”: Ví dụ: “2023-07-06” hoặc “2023/07/06”.

    • “MM/DD/YYYY” hoặc “MM-DD-YYYY”: Ví dụ: “07/06/2023” hoặc “07-06-2023”.

    • “DD/MM/YYYY” hoặc “DD-MM-YYYY”: Ví dụ: “06/07/2023” hoặc “06-07-2023”.

  2. Đối tượng ngày trong R (Date objects):

    Sử dụng hàm as.Date() để chuyển đổi ngày từ định dạng chuỗi sang đối tượng ngày tháng trong R. Ví dụ: as.Date(“2023-07-06”) sẽ tạo ra một đối tượng ngày tháng trong R.

  3. Đối tượng ngày và thời gian trong R (POSIXct objects):

    Sử dụng hàm as.POSIXct() để chuyển đổi từ định dạng chuỗi sang đối tượng ngày tháng và thời gian. Ví dụ: as.POSIXct(“2023-07-06 16:46:37”) sẽ tạo ra một đối tượng ngày tháng và thời gian trong R.

  4. Định dạng chuỗi ngắn gọn (Abbreviated format):

    • “%Y-%m-%d”: Biểu diễn theo dạng “YYYY-MM-DD”.

    • “%d/%m/%Y”: Biểu diễn theo dạng “DD/MM/YYYY”. Định dạng năm và tháng (Year and month format):

    • “%Y-%m”: Biểu diễn theo dạng “YYYY-MM”.

    • “%b %Y”: Biểu diễn theo dạng “Tháng Năm”, ví dụ: “Jul 2023” biểu diễn tháng 7 năm 2023.

  5. Định dạng theo quy tắc ISO (ISO format):

    • “%Y-W%W”: Biểu diễn theo dạng “YYYY-WW”, ví dụ: “2023-W27” biểu diễn tuần thứ 27 năm 2023.

    • “%Y-%m-%dT%H:%M:%SZ”: Biểu diễn theo dạng “YYYY-MM-DDTHH:MM:SSZ”, ví dụ: “2023-07-06T16:46:37Z”.

Đây chỉ là một số định dạng ngày tháng phổ biến trong R. Bạn cũng có thể tùy chỉnh định dạng ngày tháng bằng cách sử dụng các chuỗi định dạng khác nhau và các hàm định dạng như format().

2.3 Sử dụng packages lubridate

Trong R, package lubridate là một công cụ phổ biến để xử lý và chuyển đổi dữ liệu thời gian. Để sử dụng package này, bạn cần cài đặt tải nó vào trong môi trường làm việc R của mình bằng các bước sau:

Bước 1: Cài đặt package lubridate

Bạn có thể cài đặt package lubridate bằng cách chạy lệnh sau trong RStudio:

Nếu package đã được cài đặt trước đó, bạn có thể bỏ qua bước này.

Bước 2: Tải package lubridate

Sau khi cài đặt, bạn cần gọi package lubridate bằng lệnh sau:

library(lubridate)

2.3.1 Tạo đối tượng thời gian

Trong gói lubridate, có nhiều hàm để tạo đối tượng thời gian từ chuỗi ký tự hoặc từ các thành phần thời gian nhất định và nó chủ yếu được thành lập thông qa ba thành phần chính là y (biểu hiện cho năm), m (biểu hiện cho tháng) và cuối cùng là d (biểu hiện cho ngày) tùy thuộc vào cách tạo đối tượng của bạn mà có thể tạo ra đối tượng thời gian tương thích. Dưới đây là một số hàm tạo đối tượng thời gian phổ biến trong lubridate:

1. ymd(): Tạo đối tượng thời gian ngày-tháng-năm từ chuỗi ký tự. Ví dụ: ymd(“2022-12-31”).

2. mdy(): Tạo đối tượng thời gian tháng-ngày-năm từ chuỗi ký tự. Ví dụ: mdy(“12-31-2022”).

3. dmy(): Tạo đối tượng thời gian ngày-tháng-năm từ chuỗi ký tự. Ví dụ: dmy(“31-12-2022”).

4. ymd_hms(): Tạo đối tượng thời gian ngày-tháng-năm-giờ-phút-giây từ chuỗi ký tự. Ví dụ: ymd_hms(“2022-12-31 23:59:59”).

5. today(): Tạo đối tượng thời gian hiện tại với thông tin ngày hiện tại.

6. now(): Tạo đối tượng thời gian hiện tại với thông tin về ngày, giờ, phút và giây.

7. as_date(): Chuyển đổi một đối tượng thời gian thành đối tượng thời gian ngày, loại bỏ thông tin về giờ, phút và giây. Ví dụ: as_date(ymd_hms(“2022-12-31 23:59:59”)).

Lubridate còn cung cấp các hàm hm(), hms() và ms() để phân tích cú pháp các ngày tháng không đầy đủ từ chuỗi thành đối tượng Period. Dưới đây là mô tả khái quát về các hàm này:

  • hm(): Sử dụng để phân tích cú pháp chuỗi có định dạng “giờ:phút” thành đối tượng Period.

  • hms(): Sử dụng để phân tích cú pháp chuỗi có định dạng “giờ:phút:giây” thành đối tượng Period.

  • ms(): Sử dụng để phân tích cú pháp chuỗi có định dạng “phút:giây” thành đối tượng Period.

  • yq(): Chuyển đổi chuỗi thành ngày quý theo định dạng YQ. Ví dụ: yq(“2001: Q3”) sẽ trả về đối tượng ngày “2001-07-01” (đầu tháng quý 3).

  • my(): Chuyển đổi chuỗi thành ngày tháng theo định dạng MY. Ví dụ: my(“07-2020”)

Các hàm này tạo ra đối tượng Period, cho phép bạn biểu diễn một khoảng thời gian không đầy đủ, ví dụ như “5 phút” hoặc “2 giờ 30 phút”.

Chuyển đổi chuỗi ký tự thành đối tượng thời gian:

Để chuyển đổi một chuỗi kí tự thành đối tượng thời gian, bạn có thể sử dụng hàm ymd()dmy() là các hàm chuyển đổi từ chuỗi ký tự thành đối tượng Date, và ymd_hms() là các hàm chuyển đổi thành đối tượng POSIXct (bao gồm cả thông tin giờ phút giây). Bạn có thể lựa chọn hàm phù hợp với định dạng của chuỗi ký tự bạn có.

  1. Chuyển đổi chuỗi ký tự thành đối tượng Date
#Chuyển đổi chuỗi ký tự dạng chuẩn sang đối tượng thời gian
date_string <- "2023-07-10"
date <- ymd(date_string) #Kết quả "2023-07-10"

#Chuyển đổi chuỗi ký tự không chuẩn sang đối tượng thời gian
date_string <- "10/Jul/2023"
date <- dmy(date_string) #Kết quả "2023-07-10"
  1. Chuyển đổi chuỗi ký tự thành đối tượng POSIXct (bao gồm cả thông tin thời gian):

Sử dụng hàmymd_hms() - để tạo ra đối tượng ngày tháng với cả thông tin thời gian từ chuỗi “năm-tháng-ngày giờ:phút:giây” (Year-Month-Day hour:minute:second).

datetime_string <- "2023-07-10 12:30:15"
datetime <- ymd_hms(datetime_string) # Kết quả: "2023-07-10 12:30:15 UTC"

2.3.2 Xử lý chuỗi kí tự đặc biệt

Hàm parse_date_time()1 trong gói Lubridate là một công cụ phân tích cú pháp linh hoạt và mạnh mẽ để chuyển đổi chuỗi thành đối tượng ngày-giờ POSIXct trong R.

Hàm này cho phép bạn xác định định dạng ngày tháng trong chuỗi bằng cách sử dụng một chuỗi đặc biệt gọi là “templates”. Templates xác định các ký tự và cấu trúc đại diện cho các phần của ngày tháng (ví dụ: %d cho ngày, %m cho tháng, %Y cho năm) và thời gian (ví dụ: %H cho giờ, %M cho phút, %S cho giây).

Bạn có thể tạo templates tuỳ chỉnh của riêng mình hoặc sử dụng các templates có sẵn trong Lubridate. Hàm parse_date_time() sẽ tìm kiếm template phù hợp với chuỗi cần phân tích cú pháp và sử dụng định dạng tương ứng để chuyển đổi chuỗi thành một đối tượng POSIXct.

Ví dụ: parse_date_time(“12-25-2022 10:30:00”, orders = c(“%m-%d-%Y %H:%M:%S”))

2.3.3 Truy cập thành phần thời gian

Lubridate phân biệt giữa thời điểm trong thời gian (được biết đến như là instants()) và khoảng thời gian (được biết đến như là time spans, xem Timespan). Khoảng thời gian còn được chia thành các đối tượng Duration, Period và Interval.

Trong gói lubridate, bạn có thể dễ dàng truy cập và thao tác với các thành phần thời gian của đối tượng bằng cách sử dụng các hàm sau:

1. year(): Trả về năm của đối tượng thời gian. Ví dụ: year(ymd(“2022-12-31”)) trả về 2022.

2. month(): Trả về tháng của đối tượng thời gian. Ví dụ: month(ymd(“2022-12-31”)) trả về 12.

3. mday(): Trả về ngày trong tháng của đối tượng thời gian. Ví dụ: mday(ymd(“2022-12-31”)) trả về 31.

4. wday(): Trả về thứ trong tuần của đối tượng thời gian (từ 1 đến 7). Ví dụ: wday(ymd(“2022-12-31”)) trả về 7.

5. hour(): Trả về giờ của đối tượng thời gian. Ví dụ: hour(ymd_hms(“2022-12-31 23:59:59”)) trả về 23.

6. minute(): Trả về phút của đối tượng thời gian. Ví dụ: minute(ymd_hms(“2022-12-31 23:59:59”)) trả về 59.

7. second(): Trả về giây của đối tượng thời gian. Ví dụ: second(ymd_hms(“2022-12-31 23:59:59”)) trả về 59.

8. tz(): Trả về múi giờ của đối tượng thời gian. Ví dụ: tz(ymd_hms(“2022-12-31 23:59:59”, tz = “America/New_York”)) trả về “America/New_York”.

9. week(x): Lấy số tuần trong năm từ một đối tượng ngày giờ.

10. isoweek(x): Lấy số tuần theo chuẩn ISO 8601 từ một đối tượng ngày giờ.

11. epiweek(x): Lấy số tuần theo chuẩn epidemiological từ một đối tượng ngày giờ.

12. quarter(x): Lấy thành phần quý từ một đối tượng ngày giờ.

13. semester(x, with_year = FALSE): Lấy thành phần học kỳ từ một đối tượng ngày giờ. Nếu with_year được chỉ định là TRUE, thì kết quả sẽ bao gồm cả năm.

14. am(x): Kiểm tra xem một giờ nằm trong khoảng thời gian AM hay không.

15. pm(x): Kiểm tra xem một giờ nằm trong khoảng thời gian PM hay không.

16. dst(x): Kiểm tra xem một ngày giờ có nằm trong thời gian tiết kiệm ánh sáng ban ngày hay không.

17. leap_year(x): Kiểm tra xem một năm có phải là năm nhuận hay không.

18. update(object, …, simple = FALSE): Cập nhật một đối tượng ngày giờ bằng cách thay đổi các thành phần như năm, tháng, ngày, giờ, phút, giây, và múi giờ. Tham số simple xác định cách cập nhật, mặc định là FALSE.

Các hàm trên giúp bạn truy cập và lấy thông tin về năm, tháng, ngày, giờ, phút, giây và múi giờ từ các đối tượng thời gian trong lubridate. Bạn có thể sử dụng các hàm này để thực hiện các phép tính hoặc thao tác khác với các thành phần thời gian.

2.3.4 Thay đổi định dạng của ngày tháng

Để thay đổi định dạng của đối tượng ngày tháng bạn có thể sử dụng hàm `format()`.

Ví dụ, để thay đổi định dạng của một đối tượng ngày tháng sang định dạng “dd/mm/yyyy”, bạn có thể sử dụng câu lệnh sau:

# Tạo đối tượng ngày tháng
date <- ymd("2023-07-10")

# Thay đổi định dạng
formatted_date <- format(date, "%d/%m/%Y") 
print(formatted_date)
## [1] "10/07/2023"

Trong ví dụ này, ymd() dùng để tạo ra đối tượng ngày tháng từ chuỗi “2023-07-10”. Sau đó, format() được sử dụng để thay đổi định dạng của đối tượng ngày tháng thành “dd/mm/yyyy”.

2.3.5 Khoảng thời gian

Khoảng thời gian là một khoảng thời gian có thể có hoặc không được kết nối với một thời điểm cụ thể. Ví dụ, ba tháng là một khoảng thời gian. Một tiếng rưỡi cũng vậy. Cơ sở R sử dụng các đối tượng lớp difftime để ghi lại các khoảng thời gian. Tuy nhiên, không phải lúc nào cũng nhất quán trong cách họ mong đợi thời gian hành xử. Đôi khi thời gian trôi qua là một tiến trình đơn điệu của các khoảnh khắc đáng tin cậy về mặt toán học như trục số. Trong những trường hợp khác, thời gian phải tuân theo các quy ước và quy tắc phức tạp để thời gian trên đồng hồ mà chúng ta nhìn thấy phản ánh những gì chúng ta mong đợi quan sát được về mặt ánh sáng ban ngày, mùa và sự phù hợp với đồng hồ nguyên tử. Để điều hướng tốt hơn các sắc thái của thời gian, lubridate tạo ba lớp khoảng thời gian bổ sung, mỗi lớp có hành vi nhất quán và cụ thể: Interval, Period and Duration.

is.difftime() kiểm tra xem một đối tượng có kế thừa từ lớp difftime hay không. is.timespan() kiểm tra xem một đối tượng có kế thừa từ bất kỳ lớp nào trong bốn lớp khoảng thời gian hay không.

2.3.5.1 Interval

interval() tạo một đối tượng Interval với ngày bắt đầu và ngày kết thúc được chỉ định. Nếu ngày bắt đầu xảy ra trước ngày kết thúc, khoảng thời gian sẽ là số dương. Nếu không, nó sẽ là tiêu cực. Vectơ ký tự ở định dạng ISO 8601 được hỗ trợ từ v1.7.2.

  1. int_start()/int_end()int_start<-()/int_end<-() lần lượt là “accessors” và “setters” của ngày bắt đầu/kết thúc của một khoảng thời gian.

  2. int_flip() đảo ngược thứ tự của ngày bắt đầu và ngày kết thúc trong một khoảng thời gian. Khoảng thời gian mới diễn ra trong cùng khoảng thời gian với khoảng thời gian ban đầu nhưng có hướng ngược lại.

  3. int_shift() dịch chuyển ngày bắt đầu và ngày kết thúc của một khoảng thời gian lên hoặc xuống dòng thời gian theo một lượng xác định. Lưu ý rằng điều này có thể thay đổi độ dài chính xác của khoảng thời gian nếu khoảng thời gian bị dịch chuyển bởi một đối tượng Chu kỳ. Các khoảng thời gian được thay đổi bởi một đối tượng Thời lượng hoặc độ lệch thời gian sẽ giữ nguyên độ dài chính xác của chúng sau vài giây.

  4. int_overlaps() kiểm tra xem hai khoảng thời gian có trùng nhau không.

  5. int_standardize() đảm bảo tất cả các khoảng trong đối tượng khoảng đều dương. Nếu một khoảng không dương, hãy lật nó để nó giữ lại các điểm cuối nhưng trở nên dương.

  6. int_aligns() kiểm tra xem hai khoảng thời gian có chung một điểm cuối hay không. Hướng của mỗi khoảng thời gian được bỏ qua. int_align kiểm tra xem thời điểm sớm nhất hay mới nhất của mỗi khoảng thời gian xảy ra cùng một lúc.

  7. int_diff() trả về các khoảng xảy ra giữa các phần tử của một vectơ thời gian. int_diff() tương tự như các phương thức POSIXt và Date của diff(), nhưng trả về một đối tượng Khoảng thời gian thay vì một đối tượng khác thời gian.

interval(ymd(20090201), ymd(20090101))
## [1] 2009-02-01 UTC--2009-01-01 UTC
date1 <- ymd_hms("2009-03-08 01:59:59")
date2 <- ymd_hms("2000-02-29 12:00:00")
interval(date2, date1)
## [1] 2000-02-29 12:00:00 UTC--2009-03-08 01:59:59 UTC
interval(date1, date2)
## [1] 2009-03-08 01:59:59 UTC--2000-02-29 12:00:00 UTC
span <- interval(ymd(20090101), ymd(20090201))

### Khoảng thời gian theo tiêu chuẩn ISO

interval("2007-03-01T13:00:00Z/2008-05-11T15:30:00Z")
## [1] 2007-03-01 13:00:00 UTC--2008-05-11 15:30:00 UTC
interval("2007-03-01T13:00:00Z/P1Y2M10DT2H30M")
## [1] 2007-03-01 13:00:00 UTC--2008-05-11 15:30:00 UTC
interval("P1Y2M10DT2H30M/2008-05-11T15:30:00Z")
## [1] 2007-03-01 13:00:00 UTC--2008-05-11 15:30:00 UTC
interval("2008-05-11/P2H30M")
## [1] 2008-05-11 UTC--2010-11-11 02:00:00 UTC
### Phân tích cú pháp dễ dãi hơn (miễn là không có ký tự/ký tự gián đoạn)
interval("2008 05 11/P2hours 30minutes")
## [1] 2008-05-11 UTC--2008-05-11 02:30:00 UTC
interval("08 05 11/P 2h 30m")
## [1] 2008-05-11 UTC--2010-11-11 02:00:00 UTC
is.interval(period(months = 1, days = 15)) # FALSE
## [1] FALSE
is.interval(interval(ymd(20090801), ymd(20090809))) # TRUE
## [1] TRUE
int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int_start(int)
## [1] "2001-01-01 UTC"
int_start(int) <- ymd("2001-06-01")
int
## [1] 2001-06-01 UTC--2002-01-01 UTC
int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int_end(int)
## [1] "2002-01-01 UTC"
int_end(int) <- ymd("2002-06-01")
int
## [1] 2001-01-01 UTC--2002-06-01 UTC
int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int_length(int)
## [1] 31536000
int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int_flip(int)
## [1] 2002-01-01 UTC--2001-01-01 UTC
int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int_shift(int, duration(days = 11))
## [1] 2001-01-12 UTC--2002-01-12 UTC
int_shift(int, duration(hours = -1))
## [1] 2000-12-31 23:00:00 UTC--2001-12-31 23:00:00 UTC
int1 <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int2 <- interval(ymd("2001-06-01"), ymd("2002-06-01"))
int3 <- interval(ymd("2003-01-01"), ymd("2004-01-01"))

int_overlaps(int1, int2) # TRUE
## [1] TRUE
int_overlaps(int1, int3) # FALSE
## [1] FALSE
int <- interval(ymd("2002-01-01"), ymd("2001-01-01"))
int_standardize(int)
## [1] 2001-01-01 UTC--2002-01-01 UTC
int1 <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int2 <- interval(ymd("2001-06-01"), ymd("2002-01-01"))
int3 <- interval(ymd("2003-01-01"), ymd("2004-01-01"))

int_aligns(int1, int2) # TRUE
## [1] TRUE
int_aligns(int1, int3) # FALSE
## [1] FALSE
dates <- now() + days(1:10)
int_diff(dates)
## [1] 2023-08-09 07:47:04 +07--2023-08-10 07:47:04 +07
## [2] 2023-08-10 07:47:04 +07--2023-08-11 07:47:04 +07
## [3] 2023-08-11 07:47:04 +07--2023-08-12 07:47:04 +07
## [4] 2023-08-12 07:47:04 +07--2023-08-13 07:47:04 +07
## [5] 2023-08-13 07:47:04 +07--2023-08-14 07:47:04 +07
## [6] 2023-08-14 07:47:04 +07--2023-08-15 07:47:04 +07
## [7] 2023-08-15 07:47:04 +07--2023-08-16 07:47:04 +07
## [8] 2023-08-16 07:47:04 +07--2023-08-17 07:47:04 +07
## [9] 2023-08-17 07:47:04 +07--2023-08-18 07:47:04 +07
  1. as.interval(x, start, …)

Chuyển đổi một đối tượng thành kiểu “interval”. Đối tượng đầu vào có thể là hai thời điểm hoặc một khoảng thời gian (vd: kiểu “difftime”). as.interval có thể được sử dụng để tạo các phép biến đổi chính xác giữa các đối tượng Thời gian, đo khoảng thời gian theo đơn vị độ dài thay đổi và đối tượng Thời lượng, đo khoảng thời gian dưới dạng số giây chính xác.

Trong đó:

x: một khoảng thời gian, độ lệch thời gian, khoảng thời gian hoặc đối tượng số mô tả độ dài của khoảng thời gian

start: một đối tượng POSIXt hoặc Date mô tả khi khoảng thời gian bắt đầu

diff <- make_difftime(days = 31) # difftime
as.interval(diff, ymd("2009-01-01"))
## [1] 2009-01-01 UTC--2009-02-01 UTC
as.interval(diff, ymd("2009-02-01"))
## [1] 2009-02-01 UTC--2009-03-04 UTC
dur <- duration(days = 31) # duration
as.interval(dur, ymd("2009-01-01"))
## [1] 2009-01-01 UTC--2009-02-01 UTC
as.interval(dur, ymd("2009-02-01"))
## [1] 2009-02-01 UTC--2009-03-04 UTC
per <- period(months = 1) # period
as.interval(per, ymd("2009-01-01"))
## [1] 2009-01-01 UTC--2009-02-01 UTC
as.interval(per, ymd("2009-02-01"))
## [1] 2009-02-01 UTC--2009-03-01 UTC
as.interval(3600, ymd("2009-01-01")) # numeric
## [1] 2009-01-01 UTC--2018-11-10 UTC
  1. %within%: Kiểm tra xem khoảng thời gian này có nằm trong khoản thời gian kia không.
int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int2 <- interval(ymd("2001-06-01"), ymd("2002-01-01"))

ymd("2001-05-03") %within% int # TRUE
## [1] TRUE
int2 %within% int # TRUE
## [1] TRUE
ymd("1999-01-01") %within% int # FALSE
## [1] FALSE
## recycling (carefully note the difference between using a vector of
## intervals and list of intervals for the second argument)
dates <- ymd(c("2014-12-20", "2014-12-30", "2015-01-01", "2015-01-03"))
blackout_vector <- c(
  interval(ymd("2014-12-30"), ymd("2014-12-31")),
  interval(ymd("2014-12-30"), ymd("2015-01-03"))
)
dates %within% blackout_vector
## [1] FALSE  TRUE FALSE  TRUE
## within ANY of the intervals of a list
dates <- ymd(c("2014-12-20", "2014-12-30", "2015-01-01", "2015-01-03"))
lst <- list(
  interval(ymd("2014-12-30"), ymd("2014-12-31")),
  interval(ymd("2014-12-30"), ymd("2015-01-03"))
)
dates %within% lst
## [1] FALSE  TRUE  TRUE  TRUE
## interval within a list of intervals
int <- interval(
  ymd("2014-12-20", "2014-12-30"),
  ymd("2015-01-01", "2015-01-03")
)
int %within% lst
## [1] FALSE  TRUE

2.3.5.2 Period

Khoảng thời gian đo lường sự thay đổi trong thời gian đồng hồ xảy ra giữa hai thời điểm. Các khoảng thời gian cung cấp dự đoán mạnh mẽ về thời gian đồng hồ khi có giây nhuận, năm nhuận và thay đổi trong DST. Các hàm để làm việc với các khoảng thời gian bao gồm is.period(), as.period() and period()

Trong đó:

  1. period(num = NULL, units = “second”, …): tạo hoặc phân tích đối tượng thời gian với các giá trị đã chỉ định.
# Vectơ chu kỳ và đơn vị riêng biệt

period(c(90, 5), c("second", "minute"))
## [1] "5M 90S"
period(-1, "days")
## [1] "-1d 0H 0M 0S"
period(c(3, 1, 2, 13, 1), c("second", "minute", "hour", "day", "week"))
## [1] "20d 2H 1M 3S"
period(c(1, -60), c("hour", "minute"))
## [1] "1H -60M 0S"
period(0, "second")
## [1] "0S"
  1. as.period(): thay đổi các đối tượng lớp Interval, Duration, difftime và số thành các đối tượng lớp Period với các đơn vị được chỉ định. Hàm is.period có chức năng tương tự.
span <- interval(ymd_hms("2009-01-01 00:00:00"), ymd_hms("2010-02-02 01:01:01")) # interval
as.period(span)
## [1] "1y 1m 1d 1H 1M 1S"
as.period(span, unit = "day")
## [1] "397d 1H 1M 1S"
"397d 1H 1M 1S"
## [1] "397d 1H 1M 1S"
leap <- interval(ymd("2016-01-01"), ymd("2017-01-01"))
as.period(leap, unit = "days")
## [1] "366d 0H 0M 0S"
as.period(leap, unit = "years")
## [1] "1y 0m 0d 0H 0M 0S"
dst <- interval(
  ymd("2016-11-06", tz = "America/Chicago"),
  ymd("2016-11-07", tz = "America/Chicago")
)
as.period(dst, unit = "hours")
## [1] "25H 0M 0S"
per <- period(hours = 10, minutes = 6)
as.numeric(per, "hours")
## [1] 10.1
as.numeric(per, "minutes")
## [1] 606

2.3.5.3 Durations

Khoảng thời gian đo lượng thời gian chính xác xảy ra giữa hai thời điểm. Điều này có thể tạo ra kết quả không mong muốn liên quan đến thời gian của đồng hồ nếu giây nhuận, năm nhuận hoặc thay đổi về thời gian tiết kiệm ánh sáng ban ngày (DST) xảy ra trong khoảng thời gian.

Các hàm để làm việc với thời lượng bao gồm is.duration(), as.duration() và duration(). dseconds(), dminutes(), dhours(), ddays(), dweeks() và dyears() độ dài thuận tiện.

Trong đó:

  1. duration(num = NULL, units = “seconds”, …): tạo đối tượng thời lượng với các giá trị được chỉ định. Các mục cho các đơn vị khác nhau được tích lũy. thời lượng hiển thị dưới dạng số giây trong một khoảng thời gian. Khi số này lớn, thời lượng cũng hiển thị ước tính theo đơn vị lớn hơn, tuy nhiên, đối tượng bên dưới luôn được ghi dưới dạng số giây cố định. Đối với mục đích hiển thị và tạo, các đơn vị được chuyển đổi thành giây sử dụng độ dài phổ biến nhất của chúng tính bằng giây. Phút = 60 giây, giờ = 3600 giây, ngày = 86400 giây, tuần = 604800. Các đơn vị lớn hơn tuần không được sử dụng do có thể thay đổi.
# Vectơ chu kỳ và đơn vị riêng biệt

duration(90, "seconds")
## [1] "90s (~1.5 minutes)"
duration(1.5, "minutes")
## [1] "90s (~1.5 minutes)"
duration(-1, "days")
## [1] "-86400s (~-1 days)"
  1. as.duration(): thay đổi các đối tượng lớp Interval, Period và số thành các đối tượng Duration. Các đối tượng số được thay đổi thành các đối tượng Duration với đơn vị giây bằng giá trị số
span <- interval(ymd("2009-01-01"), ymd("2009-08-01")) # interval
as.duration(span)
## [1] "18316800s (~30.29 weeks)"
as.duration(10) # numeric
## [1] "10s"
dur <- duration(hours = 10, minutes = 6)
as.numeric(dur, "hours")
## [1] 10.1
as.numeric(dur, "minutes")
## [1] 606
  1. Các hàm còn lại

Nó có nghĩa giống như các hàm trước đã giới thiệu qua (xem lại mục 2.3.3) nhưng mở rộng ra thêm

dseconds(1)
## [1] "1s"
dminutes(3.5)
## [1] "210s (~3.5 minutes)"
x <- ymd("2009-08-03", tz = "America/Chicago")
x + ddays(1) + dhours(6) + dminutes(30)
## [1] "2009-08-04 06:30:00 CDT"
x + ddays(100) - dhours(8)
## [1] "2009-11-10 15:00:00 CST"
class(as.Date("2009-08-09") + ddays(1)) # Giữ lại lớp Date 
## [1] "Date"
as.Date("2009-08-09") + dhours(12)
## [1] "2009-08-09 12:00:00 UTC"
class(as.Date("2009-08-09") + dhours(12))
## [1] "POSIXct" "POSIXt"
# chuyển đổi sang lớp POSIXct để chứa các đơn vị thời gian

dweeks(1) - ddays(7)
## [1] "0s"
c(1:3) * dhours(1)
## [1] "3600s (~1 hours)"  "7200s (~2 hours)"  "10800s (~3 hours)"

2.3.6 Làm tròn và xử lý các ngày tháng:

Các hàm `ceiling_date()`, `floor_date()``round_date()` là những hàm trong gói Lubridate của R và được sử dụng để làm tròn và xử lý các ngày tháng.

  • ceiling_date(): Hàm này làm tròn ngày lên đến đơn vị xác định gần nhất. Đơn vị có thể là năm, tháng, tuần, ngày, giờ, phút hoặc giây.

  • floor_date(): Hàm này làm tròn ngày xuống đến đơn vị xác định gần nhất. Tương tự như ceiling_date(), bạn có thể xác định đơn vị là năm, tháng, tuần, ngày, giờ, phút hoặc giây.

  • round_date(): Hàm này làm tròn ngày đến đơn vị xác định gần nhất. Các đơn vị tùy chọn cũng tương tự như hai hàm trước.

round_date(
  x,
  unit = "second",
  week_start = getOption("lubridate.week.start", 7)
)
## [1] "2009-08-03 CDT"
floor_date(
  x,
  unit = "seconds",
  week_start = getOption("lubridate.week.start", 7)
)
## [1] "2009-08-03 CDT"
ceiling_date(
  x,
  unit = "seconds",
  week_start = getOption("lubridate.week.start", 7)
)
## [1] "2009-08-03 CDT"

Trong đó:

x: một vectơ của các đối tượng ngày giờ

unit: một chuỗi, đối tượng Chu kỳ hoặc đối tượng ngày giờ. Khi một chuỗi đơn, nó chỉ định một đơn vị thời gian hoặc bội số của một đơn vị được làm tròn thành. Đơn vị cơ sở hợp lệ là giây, phút, giờ, ngày, tuần, tháng, hai tháng, quý, mùa, nửa năm và năm. Làm tròn thành bội số của đơn vị (trừ weeks) được hỗ trợ.

Khi đơn vị là đối tượng ngày giờ, việc làm tròn được thực hiện đến phần tử gần nhất trong đơn vị. Nếu phạm vi của vectơ đơn vị không bao gồm phạm vi của x bare_date() và floor_date() làm tròn thành max(x) và min(x) đối với các phần tử nằm ngoài phạm vi (đơn vị).

week_start: ngày bắt đầu tuần (Mặc định là 7, Chủ nhật. Đặt lubridate.week.start để ghi đè).

# In phân số
options(digits.secs = 6)

x <- ymd_hms("2009-08-03 12:01:59.23")
round_date(x, ".5s")
## [1] "2009-08-03 12:01:59 UTC"
round_date(x, "sec")
## [1] "2009-08-03 12:01:59 UTC"
round_date(x, "second")
## [1] "2009-08-03 12:01:59 UTC"
round_date(x, "minute")
## [1] "2009-08-03 12:02:00 UTC"
round_date(x, "5 mins")
## [1] "2009-08-03 12:00:00 UTC"
round_date(x, "hour")
## [1] "2009-08-03 12:00:00 UTC"
round_date(x, "2 hours")
## [1] "2009-08-03 12:00:00 UTC"
round_date(x, "day")
## [1] "2009-08-04 UTC"
round_date(x, "week")
## [1] "2009-08-02 UTC"
round_date(x, "month")
## [1] "2009-08-01 UTC"
round_date(x, "bimonth")
## [1] "2009-09-01 UTC"
round_date(x, "quarter") == round_date(x, "3 months")
## [1] TRUE
round_date(x, "halfyear")
## [1] "2009-07-01 UTC"
round_date(x, "year")
## [1] "2010-01-01 UTC"
x <- ymd_hms("2009-08-03 12:01:59.23")
floor_date(x, ".1s")
## [1] "2009-08-03 12:01:59.2 UTC"
floor_date(x, "second")
## [1] "2009-08-03 12:01:59 UTC"
floor_date(x, "minute")
## [1] "2009-08-03 12:01:00 UTC"
floor_date(x, "hour")
## [1] "2009-08-03 12:00:00 UTC"
floor_date(x, "day")
## [1] "2009-08-03 UTC"
floor_date(x, "week")
## [1] "2009-08-02 UTC"
floor_date(x, "month")
## [1] "2009-08-01 UTC"
floor_date(x, "bimonth")
## [1] "2009-07-01 UTC"
floor_date(x, "quarter")
## [1] "2009-07-01 UTC"
floor_date(x, "season")
## [1] "2009-06-01 UTC"
floor_date(x, "halfyear")
## [1] "2009-07-01 UTC"
floor_date(x, "year")
## [1] "2009-01-01 UTC"
x <- ymd_hms("2009-08-03 12:01:59.23")
ceiling_date(x, ".1 sec") # đại diện không chính xác ở 0,1 giây 
## [1] "2009-08-03 12:01:59.2 UTC"
ceiling_date(x, "second")
## [1] "2009-08-03 12:02:00 UTC"
ceiling_date(x, "minute")
## [1] "2009-08-03 12:02:00 UTC"
ceiling_date(x, "5 mins")
## [1] "2009-08-03 12:05:00 UTC"
ceiling_date(x, "hour")
## [1] "2009-08-03 13:00:00 UTC"
ceiling_date(x, "day")
## [1] "2009-08-04 UTC"
ceiling_date(x, "week")
## [1] "2009-08-09 UTC"
ceiling_date(x, "month")
## [1] "2009-09-01 UTC"
ceiling_date(x, "bimonth") == ceiling_date(x, "2 months")
## [1] TRUE
ceiling_date(x, "quarter")
## [1] "2009-10-01 UTC"
ceiling_date(x, "season")
## [1] "2009-09-01 UTC"
ceiling_date(x, "halfyear")
## [1] "2010-01-01 UTC"
ceiling_date(x, "year")
## [1] "2010-01-01 UTC"
## Đối số đơn vị thời gian
floor_date(x, days(2))
## [1] "2009-08-03 UTC"
floor_date(x, years(1))
## [1] "2009-01-01 UTC"
## giống nhau nhưng ngày được làm tròn lên
ceiling_date(ymd_hms("2000-01-01 00:00:00"), "month")
## [1] "2000-01-01 UTC"
ceiling_date(ymd("2000-01-01"), "month")
## [1] "2000-02-01"
## Nếu `TRUE`, cả thời gian và ngày trên ranh giới đều được làm tròn lên
ceiling_date(ymd_hms("2000-01-01 00:00:00"), "month", change_on_boundary = TRUE)
## [1] "2000-02-01 UTC"
ceiling_date(ymd("2000-01-01"), "month")
## [1] "2000-02-01"
##Nếu `FALSE`, cả thời điểm và ngày trên ranh giới đều giữ nguyên
ceiling_date(ymd_hms("2000-01-01 00:00:00"), "month", change_on_boundary = FALSE)
## [1] "2000-01-01 UTC"
ceiling_date(ymd("2000-01-01"), "month")
## [1] "2000-02-01"
x <- ymd_hms("2000-01-01 00:00:00")
ceiling_date(x, "month")
## [1] "2000-01-01 UTC"
ceiling_date(x, "month", change_on_boundary = TRUE)
## [1] "2000-02-01 UTC"

2.3.7 Xử lý vấn đề về múi giờ, giờ mùa và thứ tự ngày tháng:

R nhận ra ~600 múi giờ. Mỗi mã hóa múi giờ, Ánh sáng ban ngày Tiết kiệm thời gian và các biến thể lịch sử cho một khu vực. R chỉ định một múi giờ trên mỗi vectơ.

Sử dụng múi giờ UTC để tránh Tiết kiệm ánh sáng ban ngày.

OlsonNames() Trả về danh sách tên múi giờ hợp lệ. OlsonNames()

Sys.timezone() Nhận múi giờ hiện tại.

  1. Múi giờ (Time Zones):
  • with_tz(time, tzone = ““, …): trả về ngày giờ vì nó sẽ xuất hiện ở một múi giờ khác. Thời điểm thực tế của thời gian được đo không thay đổi, chỉ thay đổi múi giờ mà nó được đo. with_tz mặc định là múi giờ Phối hợp Quốc tế (UTC) khi một múi giờ không được nhận dạng được nhập vào.

    Trong đó:

    Time: một đối tượng POSIXct, POSIXlt, Date, chron date-time hoặc một đối tượng data.frame. Khi data.frame, tất cả các phần tử POSIXt của data.frame được xử lý bằng with_tz() và data.frame mới được trả về.

    tzone: một chuỗi ký tự chứa múi giờ cần chuyển đổi sang. R phải nhận dạng tên có trong chuỗi dưới dạng múi giờ trên hệ thống của bạn.

x <- ymd_hms("2009-08-07 00:00:01", tz = "America/New_York")
with_tz(x, "GMT")
## [1] "2009-08-07 04:00:01 GMT"

Để kiểm tra múi giờ hiện tại, bạn có thể sử dụng hàm `now()` kết hợp với `tz()` như sau: `tz(now())` sẽ trả về múi giờ hiện tại.

  • force_tz(time, tzone = ““, roll_dst = c(”NA”, “post”), roll = NULL, …) hoặc force_tzs(): trả về ngày giờ có cùng thời gian đồng hồ với thời gian đầu vào, nhưng ở múi giờ mới. force_tzs là phiên bản song song của force_tz, nghĩa là mọi phần tử từ đối số time được khớp với múi giờ tương ứng trong đối số tzones.

    Trong đó: Các thành phần trong force_tz hầu như khá giống với with_tz chỉ thêm roll_dst : là một vectơ chuỗi có độ dài một hoặc hai. Khi hai giá trị được cung cấp, chúng chỉ định cách cuộn thời gian ngày khi chúng rơi vào các chuyển đổi DST “bị bỏ qua” và “lặp lại” tương ứng. Một giá trị duy nhất được sao chép theo chiều dài của hai.

x <- ymd_hms("2009-08-07 00:00:01", tz = "America/New_York")
force_tz(x, "UTC")
## [1] "2009-08-07 00:00:01 UTC"
force_tz(x, "Europe/Amsterdam")
## [1] "2009-08-07 00:00:01 CEST"
# Bỏ qua DST
y <- ymd_hms("2010-03-14 02:05:05 UTC")
force_tz(y, "America/New_York", roll_dst = "NA")
## [1] NA
force_tz(y, "America/New_York", roll_dst = "pre")
## [1] "2010-03-14 01:05:05 EST"
force_tz(y, "America/New_York", roll_dst = "boundary")
## [1] "2010-03-14 03:00:00 EDT"
force_tz(y, "America/New_York", roll_dst = "post")
## [1] "2010-03-14 03:05:05 EDT"
#Lặp lại DST
y <- ymd_hms("2014-11-02 01:35:00", tz = "UTC")
force_tz(y, "America/New_York", roll_dst = "NA")
## [1] NA
force_tz(y, "America/New_York", roll_dst = "pre")
## [1] "2014-11-02 01:35:00 EDT"
force_tz(y, "America/New_York", roll_dst = "boundary")
## [1] "2014-11-02 01:00:00 EST"
force_tz(y, "America/New_York", roll_dst = "post")
## [1] "2014-11-02 01:35:00 EST"
# DST bị bỏ qua và lặp lại
y <- ymd_hms("2010-03-14 02:05:05 UTC", "2014-11-02 01:35:00", tz = "UTC")
force_tz(y, "America/New_York", roll_dst = c("NA", "pre"))
## [1] NA                        "2014-11-02 01:35:00 EDT"
force_tz(y, "America/New_York", roll_dst = c("boundary", "post"))
## [1] "2010-03-14 03:00:00 EDT" "2014-11-02 01:35:00 EST"
  1. Giờ mùa (Daylight Saving Time):

    • Để xác định xem một thời điểm có trong giờ mùa hay không, bạn có thể sử dụng hàm `isdst()`. Ví dụ: `isdst(date_string)` sẽ trả về TRUE nếu `date_string` nằm trong giờ mùa.

    • Để chuyển đổi giữa các múi giờ có hoặc không có giờ mùa, bạn có thể sử dụng hàm `force_tz()`. Ví dụ: `force_tz(date_string, "America/New_York")` sẽ áp dụng giờ mùa cho `date_string` theo múi giờ New York.

  2. Thứ tự ngày tháng (Date-Time Order):

    • Gói lubridate sử dụng thứ tự ngày-tháng chuẩn quốc tế (ISO 8601) mặc định.

    • Để tạo một đối tượng thời gian từ một chuỗi ngày tháng trong định dạng cụ thể, bạn có thể sử dụng các hàm như `ymd()` (năm-tháng-ngày), `dmy()` (ngày-tháng-năm), `mdy()` (tháng-ngày-năm), vv.

Ví dụ: `ymd("2023-07-10")` sẽ tạo một đối tượng thời gian đại diện cho ngày 10 tháng 7 năm 2023.

2.3.8 Tính toán với thời gian

Các phép tính cơ bản

Trong thư viện lubridate của ngôn ngữ lập trình R, có một số hàm hết sức hữu ích để làm việc với ngày tháng, bao gồm + (cộng), - (trừ), %+% (tăng/điều chỉnh) và %-% (giảm/điều chỉnh). Dưới đây là các giải thích về mỗi hàm:

  • +: Hàm này cho phép bạn cộng thêm một khoảng thời gian vào một đối tượng ngày tháng. Ví dụ: date + days(3) sẽ trả về ngày tháng tăng lên 3 ngày.

  • -: Hàm này cho phép bạn trừ đi một khoảng thời gian từ một đối tượng ngày tháng. Ví dụ: date - weeks(2) sẽ trả về ngày tháng giảm đi 2 tuần.

  • %+%: Hàm này tăng hoặc điều chỉnh các thành phần của đối tượng ngày tháng. Ví dụ: date %+% years(2) sẽ tăng thêm 2 năm vào ngày tháng.

  • %-%: Hàm này giảm hoặc điều chỉnh các thành phần của đối tượng ngày tháng. Ví dụ: date %-% months(6) sẽ giảm đi 6 tháng từ ngày tháng.

Tính toán khoảng cách thời gian giữa hai ngày hay thời điểm:

  1. Tính toán khoảng cách giữa hai ngày:

    • Sử dụng hàm `interval()` để tạo khoảng thời gian giữa hai ngày/thời điểm. Ví dụ: interval(my_date1, my_date2)

    • Sử dụng hàm as.duration() để chuyển đổi khoảng thời gian thành đơn vị thời gian (giờ, phút, giây, vv.). Ví dụ: as.duration(interval(my_date1, my_date2))

    • Sử dụng hàm as.period() để chuyển đổi khoảng thời gian thành chuỗi thời gian dễ đọc. Ví dụ: as.period(interval(my_date1, my_date2))

  2. Tính toán khoảng cách giữa hai thời điểm:

    • Sử dụng hàm - để trừ hai đối tượng thời gian. Ví dụ: my_datetime2 - my_datetime1

    • Sử dụng hàm as.duration() để chuyển đổi khoảng thời gian thành đơn vị thời gian (giờ, phút, giây, vv.). Ví dụ: as.duration(my_datetime2 - my_datetime1)

    • Sử dụng hàm as.period() để chuyển đổi khoảng thời gian thành chuỗi thời gian dễ đọc. Ví dụ: as.period(my_datetime2 - my_datetime1)

Lưu ý rằng trong các ví dụ trên, my_date1, my_date2, my_datetime1, và my_datetime2 là các đối tượng thời gian bạn cần tính toán khoảng cách.

  1. So sánh ngày:

    • `>` - So sánh hai ngày, kiểm tra xem ngày thứ nhất có lớn hơn ngày thứ hai không.

    • `<` - So sánh hai ngày, kiểm tra xem ngày thứ nhất có nhỏ hơn ngày thứ hai không.

    • `==` - So sánh hai ngày, kiểm tra xem ngày thứ nhất có bằng ngày thứ hai không.

Tính toán thời gian chạy chương trình (runtime) và thời gian chờ đợi (wait time).

Chúng ta có thể sử dụng hàm system.time() để tính thời gian chạy chương trình và hàm Sys.sleep() để tạo thời gian chờ đợi.

  1. Tính thời gian chạy chương trình với hàm system.time()
start_time <- system.time({
  # Đoạn code chương trình của bạn
})

run_time <- start_time[3]  # Thời gian chạy chương trình tính bằng giây
  1. Tạo thời gian chờ đợi với hàm Sys.sleep()
wait_time <- 5  # Thời gian chờ đợi là 5 giây
Sys.sleep(wait_time)  # Tạo thời gian chờ đợi

3 CHƯƠNG III Thực hành

3.1 Dữ liệu

Trong phần này, chúng em sẽ sử dụng một bộ data cụ thể để thao tác và tìm hiểu rõ các chức năng trong package lubridate.

Tập dữ liệu “flights” trong gói “nycflights13” là một tập dữ liệu chứa thông tin về các chuyến bay trong khu vực New York. Tập dữ liệu này cung cấp thông tin về các chuyến bay như thời gian khởi hành, thời gian đến, ngày bay, địa điểm xuất phát và đích, hãng hàng không, thời tiết và các thông tin khác liên quan đến chuyến bay. Tập dữ liệu flights được sử dụng rộng rãi trong các bài toán phân tích dữ liệu và học máy liên quan đến lưu lượng chuyến bay và hãng hàng không.

336776 quan sát với 19 biến:

Tập dữ liệu “flights” trong gói “nycflights13” bao gồm 336776 quan sát với 19 biến sau:

  1. year: Năm của chuyến bay (số nguyên).

  2. month: Tháng của chuyến bay (số nguyên).

  3. day: Ngày của chuyến bay (số nguyên).

  4. dep_time: Thời gian khởi hành thực tế, theo định dạng HHMM (số nguyên).

  5. sched_dep_time: Thời gian khởi hành dự kiến, theo định dạng HHMM (số nguyên).

  6. dep_delay: Độ trễ so với thời gian khởi hành dự kiến, tính bằng phút (số nguyên).

  7. arr_time: Thời gian đến thực tế, theo định dạng HHMM (số nguyên).

  8. sched_arr_time: Thời gian đến dự kiến, theo định dạng HHMM (số nguyên).

  9. arr_delay: Độ trễ so với thời gian đến dự kiến, tính bằng phút (số nguyên).

  10. carrier: Mã hãng hàng không (chuỗi ký tự).

  11. flight: Số hiệu chuyến bay (số nguyên).

  12. tailnum: Số hiệu máy bay (chuỗi ký tự).

  13. origin: Sân bay xuất phát (chuỗi ký tự).

  14. dest: Sân bay đích (chuỗi ký tự).

  15. air_time: Thời gian bay tính bằng phút (số nguyên).

  16. distance: Khoảng cách bay tính bằng dặm (số nguyên).

  17. hour: Giờ của thời gian khởi hành dự kiến, theo định dạng HH (số nguyên).

  18. minute: Phút của thời gian khởi hành dự kiến, theo định dạng MM (số nguyên).

  19. time_hour: Thời gian khởi hành dự kiến, theo định dạng YYYY-MM-DD HH:MM (thời gian).

Những biến này cung cấp thông tin chi tiết về các chuyến bay trong tập dữ liệu “flights”.

library(tidyverse)
library(lubridate)
library(nycflights13)
data('flights')
f <- flights
f <- na.omit(f) 
head(f)
## # A tibble: 6 × 19
##    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
## 1  2013     1     1      517            515         2      830            819
## 2  2013     1     1      533            529         4      850            830
## 3  2013     1     1      542            540         2      923            850
## 4  2013     1     1      544            545        -1     1004           1022
## 5  2013     1     1      554            600        -6      812            837
## 6  2013     1     1      554            558        -4      740            728
## # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## #   hour <dbl>, minute <dbl>, time_hour <dttm>
str(f)
## tibble [327,346 × 19] (S3: tbl_df/tbl/data.frame)
##  $ year          : int [1:327346] 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month         : int [1:327346] 1 1 1 1 1 1 1 1 1 1 ...
##  $ day           : int [1:327346] 1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_time      : int [1:327346] 517 533 542 544 554 554 555 557 557 558 ...
##  $ sched_dep_time: int [1:327346] 515 529 540 545 600 558 600 600 600 600 ...
##  $ dep_delay     : num [1:327346] 2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_time      : int [1:327346] 830 850 923 1004 812 740 913 709 838 753 ...
##  $ sched_arr_time: int [1:327346] 819 830 850 1022 837 728 854 723 846 745 ...
##  $ arr_delay     : num [1:327346] 11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ carrier       : chr [1:327346] "UA" "UA" "AA" "B6" ...
##  $ flight        : int [1:327346] 1545 1714 1141 725 461 1696 507 5708 79 301 ...
##  $ tailnum       : chr [1:327346] "N14228" "N24211" "N619AA" "N804JB" ...
##  $ origin        : chr [1:327346] "EWR" "LGA" "JFK" "JFK" ...
##  $ dest          : chr [1:327346] "IAH" "IAH" "MIA" "BQN" ...
##  $ air_time      : num [1:327346] 227 227 160 183 116 150 158 53 140 138 ...
##  $ distance      : num [1:327346] 1400 1416 1089 1576 762 ...
##  $ hour          : num [1:327346] 5 5 5 5 6 5 6 6 6 6 ...
##  $ minute        : num [1:327346] 15 29 40 45 0 58 0 0 0 0 ...
##  $ time_hour     : POSIXct[1:327346], format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...
##  - attr(*, "na.action")= 'omit' Named int [1:9430] 472 478 616 644 726 734 755 839 840 841 ...
##   ..- attr(*, "names")= chr [1:9430] "472" "478" "616" "644" ...

3.2 Phân tích dữ liệu

Tập dữ liệu “flights” trong gói “nycflights13” là một tập dữ liệu chi tiết về các chuyến bay trong khu vực New York. Bây giờ chúng ta có thể tiến hành phân tích tập dữ liệu này để tìm hiểu thêm về các chuyến bay.

3.2.1 Thống kê tổng quan:

Quan sát tập dữ liệu, ta thấy cột ngày tháng và thời gian hiển thị ở từng cột khác nhau, để dễ phân tích hơn ta sẽ dùng hàm make_datetime để tạo đối tượng ngày tháng, năm.

Tạo 1 function tên make_datetime_100 trong đó sử dụng hàm make_datetime() với thành phần là các cột năm, tháng, ngày, giờ, phút.

Vì các cột có đuôi time hiển thị dưới dạng hhmm nên time %/% 100 sẽ tính ra giờ ( %/% là toán tử tính thương số) và time %% 100 sẽ tính ra phút (%% là toán tử tính phần dư)

make_datetime_100 <- function(year, month, day, time) {
  make_datetime(year, month, day, time %/% 100, time %% 100)
}

Sử dụng function mới vừa tạo để tạo thêm các cột mới với định dạng ngày, tháng, năm. Trong đó: dep_time là cột thời gian khởi hành thực tế, arr_time là cột thời gian đáp thực tế, shed_dep_time là thời gian khởi hành dự kiến, shed_arr_time là thời gian đáp dự kiến

f <- f %>% 
  filter(!is.na(dep_time), !is.na(arr_time)) %>% 
  mutate(
    dep_time = make_datetime_100(year, month, day, dep_time),
    arr_time = make_datetime_100(year, month, day, arr_time),
    sched_dep_time = make_datetime_100(year, month, day, sched_dep_time),
    sched_arr_time = make_datetime_100(year, month, day, sched_arr_time)) %>%
  select(origin, dest, ends_with("delay"), ends_with("time"), carrier, flight, tailnum, distance )

Trong tập dữ liệu, có những chuyến bay xuyên đêm nhưng ta đang sử dụng ngày giống nhau cho cấc chuyến bay đó, nhưng trên thực tế các chuyến bay này đến vào ngày hôm sau. Ta có thể điều chỉnh điều này bằng cách cộng thêm 1 ngày vào thời gian đáp máy bay của các chuyến xuyên đêm.

f <- f %>% 
  mutate(
  
    # Tạo thêm cột mới overnight trong đó sử dụng '<' để so sánh giờ đáp và giờ bay. Những chuyến bay xuyên đêm sẽ có giờ đáp nhỏ hơn giờ bay, ví dụ bay lúc 23h và đáp lúc 5h. Những cột đáp ứng được điều kiện này sẽ cho kết quả 'TRUE', còn lại sẽ hiển thị 'FALSE'.
    overnight = arr_time < dep_time,
    
    # Tạo cột arr_time mới sẽ bằng cột arr_time cũ cộng cho thêm 1 ngày nếu giá trị tương ứng ở cột overnight là 'TRUE'
    arr_time = arr_time + days(overnight * 1),
    
    # Tương tự với cột shed_dep_time
    sched_arr_time = sched_arr_time + days(overnight * 1),
    
    # Tạo cột real_air_time hiển thị thời gian bay thực bằng cách lấy cột thời gian đáp vừa tạo trừ cho cột thời gian bay.
     real_air_time = arr_time - dep_time)

head(f,10)
## # A tibble: 10 × 15
##    origin dest  dep_delay arr_delay dep_time                  
##    <chr>  <chr>     <dbl>     <dbl> <dttm>                    
##  1 EWR    IAH           2        11 2013-01-01 05:17:00.000000
##  2 LGA    IAH           4        20 2013-01-01 05:33:00.000000
##  3 JFK    MIA           2        33 2013-01-01 05:42:00.000000
##  4 JFK    BQN          -1       -18 2013-01-01 05:44:00.000000
##  5 LGA    ATL          -6       -25 2013-01-01 05:54:00.000000
##  6 EWR    ORD          -4        12 2013-01-01 05:54:00.000000
##  7 EWR    FLL          -5        19 2013-01-01 05:55:00.000000
##  8 LGA    IAD          -3       -14 2013-01-01 05:57:00.000000
##  9 JFK    MCO          -3        -8 2013-01-01 05:57:00.000000
## 10 LGA    ORD          -2         8 2013-01-01 05:58:00.000000
## # ℹ 10 more variables: sched_dep_time <dttm>, arr_time <dttm>,
## #   sched_arr_time <dttm>, air_time <dbl>, carrier <chr>, flight <int>,
## #   tailnum <chr>, distance <dbl>, overnight <lgl>, real_air_time <drtn>
  • Số lượng chuyến bay trong tập dữ liệu.

Dựa vào tập dữ liệu, ta thấy có 336776 quan sát, như vậy, số lượng chuyến bay trong tập dữ liệu này cũng là 336776 chuyến

  • Số lượng chuyến bay theo ngày

Ta sử dụng cột dep_time để vẽ biểu đồ dạng freqpoly (biểu đồ biểu thị tần suất theo dạng đường), với binwidth của biến thời gian được tính bằng giây.

f %>% 
  ggplot(aes(dep_time)) + 
  # Khoảng cách các giá trị trong cột x là 1 ngày (1 day = 86400s)
  geom_freqpoly(binwidth = 86400)+ 
  labs(x='Ngày', y='Số lượng chuyến bay', title = 'Số lượng chuyến bay theo ngày')

  • Số lượng chuyến bay theo ngày trong một tháng

Gỉa sử nếu ta muốn vẽ biểu đồ hiển thị số lượng chuyến bay theo ngày trong tháng 1

f %>% 
 
   # Sử dụng hàm ymd() để tạo ra đối tượng ngày tháng năm là '2013-02-01' và lọc ra những chuyến bay có ngày nhỏ hơn đối tượng này (tức lag những chuyến bay trong tháng 1) 
  filter(dep_time < ymd(20130201)) %>% 
 
   ggplot(aes(dep_time)) + 
 # Khoảng cách các giá trị trong cột x là 1 ngày (1 day = 86400s)
   geom_freqpoly(binwidth = 86400)+
  labs(x= 'Các ngày trong tháng', y='Số lượng chuyến bay', title = 'Số lượng chuyến bay theo từng ngày trong tháng 1')

  • Số lượng chuyến bay xuất phát theo giờ trong một ngày

Tương tự ở trên, ta cũng sử dụng hàm ymd(20130102) để tạo ra đối tượng ngày 2013-01-02 và lọc ra những chuyến bay nhỏ hơn ngày này.

f %>% 
  filter(dep_time < ymd(20130102)) %>% 
  ggplot(aes(dep_time)) + 
  geom_freqpoly(binwidth = 3600, color = 'blue')+    # 3600s = 1 hour
  labs(x= 'Giờ', y= ' Số chuyến bay', title = 'Số lượng chuyến bay theo giờ trong ngày 1/1')

  • Số lượng chuyến bay theo tuần

Ta sẽ làm tròn thời gian bay đến giá trị gần nhất theo đơn vị là tuần bằng hàm round_date() theo đơn vị là tuần.

Gía trị trả về sẽ là các ngày chủ nhật trong tuần. Nếu ngày nằm ở đầu tuần sẽ làm tròn đến chủ nhật của tuần trước đó, nếu nằm ở cuối tuần sẽ làm trong đến chủ nhật của chính tuần đó.

f %>% 
  count(week = round_date(dep_time, "week")) %>% 
  ggplot(aes(week, n)) +
    geom_line(color = 'brown', linewidth = 1)+
    labs(x= 'Tuần', y='Số chuyến bay', title = 'Thống kê số chuyến bay theo tuần')

  • Số lượng chuyến bay trong tuần với cuối tuần

Tạo cột mới tên wday trong đó sử dụng hàm wday() để quy về thứ trong tuần theo thời gian bay, sau đó đưa vào ggplot để quan sát.

f <- f %>% mutate(wday = wday(dep_time, label = TRUE, abbr = FALSE))


ggplot(f,aes(x = wday, y=after_stat(count))) +
  geom_bar(fill= 'lightpink')+
   geom_text(aes(label = scales::percent(after_stat(count/sum(count)))),stat = 'count' , color = 'black', vjust = -.1)+
  labs(x= 'Thứ' , y= 'Số lượng', title ='Số lượng chuyến bay trong tuần')

3.2.2 Độ trễ chuyến bay:

  • Xác định mối quan hệ giữa giờ khởi hành dự kiến và độ trễ.
f1 <- f

sched_dep <-  f1 %>% 
# Sử dụng hàm hour() để trích xuất giờ trong cột shed_dep_time và tạo cột mới tên dep_hour với giá trị giờ vừa lấy được
  mutate(dep_hour = hour(sched_dep_time)) %>% 

# Phân nhóm dữ liệu theo biến dep_hour(giờ khởi hành) với giá trị điền vào là trung bình số phút bị trễ 
  group_by(dep_hour)%>% 
  summarise(
    avg_dep_delay = mean(dep_delay, na.rm = TRUE), n=n()) 
# Vẽ đồ thị phân tán và đường hồi quy thể hiện mối quan hệ giữa giờ khỏi hành và độ trễ
ggplot(sched_dep, aes(x=dep_hour, y=avg_dep_delay)) +
  geom_point()+
  geom_smooth(formula = y~x, method = 'lm', na.rm = TRUE)+
  scale_x_continuous(breaks = seq(from =1, to = 24, by = 2))+
  scale_y_continuous(breaks = seq(from= 0, to = 25, by = 2))+
  labs( x= 'Giờ khởi hành', y ='Trung bình số phút bị trễ', title = 'Mối quan hệ giữa giờ khởi hành dự kiến và độ trễ')

Đường hồi quy là đường dộc lên cho thấy giờ khởi hành và số phút bị trễ có mối quan hệ thuận với nhau, cụ thể giờ khởi hành càng muộn thì số phút bị trễ càng nhiều. Ta có thể thấy thường những chuyến bay trong khoảng 19h đến 21h có độ trễ lớn nhất (trung bình là 24 phút).

  • Xác định mối quan hệ giữa độ trễ khởi hành và độ trễ đến.
lm_result <- lm(formula = arr_delay ~ dep_delay ,data = f1)
summary(lm_result)
## 
## Call:
## lm(formula = arr_delay ~ dep_delay, data = f1)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -107.587  -11.005   -1.883    8.938  201.938 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -5.8994935  0.0330195  -178.7   <2e-16 ***
## dep_delay    1.0190929  0.0007864  1295.8   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 18.03 on 327344 degrees of freedom
## Multiple R-squared:  0.8369, Adjusted R-squared:  0.8369 
## F-statistic: 1.679e+06 on 1 and 327344 DF,  p-value: < 2.2e-16
ggplot(f1, aes(x= dep_delay, y= arr_delay))+
  geom_point()+
  geom_smooth(formula = y~x,method ='lm', na.rm =TRUE )+
  labs(x='Độ trễ khởi hành', y='Độ trễ đến')

Từ đồ thị, ta thấy đường hồi quy là đường dốc lên cho thấy độ trễ khởi hành có mối quan hệ tuận tuyến tính với độ trễ lúc đến. Đường thẳng này khá dốc cho thấy 2 biến này có độ tương quan mạnh, gần như là tuyệt đối. Như vậy, độ trễ lúc khởi hành càng lớn thì độ trễ lúc đến càng lớn.

  1. Thời gian bay:
  • Xem thời gian bay trung bình của các chuyến bay.
# Sử dụng hàm group_by() để phân nhóm dữ liệu theo sân bay cất cánh và sân bay đáp với giá trị tương tứng là thời gian bay trung bình và tần số xuất hiện của đường bay đó
avgtime <-f1 %>% group_by(origin,dest) %>% summarise(mean_air_time = mean(air_time),n=n()) 
## `summarise()` has grouped output by 'origin'. You can override using the
## `.groups` argument.
head(avgtime)
## # A tibble: 6 × 4
## # Groups:   origin [1]
##   origin dest  mean_air_time     n
##   <chr>  <chr>         <dbl> <int>
## 1 EWR    ALB            31.8   418
## 2 EWR    ANC           413.      8
## 3 EWR    ATL           112.   4876
## 4 EWR    AUS           211.    957
## 5 EWR    AVL            89.8   251
## 6 EWR    BDL            25.5   412

Cột mean_air_time ở trên đang hiển thị ở dạng số phút. Ta sẽ sử dụng hàm hms() để chuyển số phút về định dạng giờ:phút:giây. Tuy nhiên để gọn gọn hơn, ta sẽ chỉ trích xuất giờ:phút bằng hàm substr().

# Chuyển đổi số phút thành giờ
avgtime$mean_air_time <- substr(as.character(hms::round_hms(hms::hms(minutes = avgtime$mean_air_time), secs = 60)),1,5)

avgtime %>% pivot_wider(names_from = origin , id_cols = dest, values_from=mean_air_time)
## # A tibble: 104 × 4
##    dest  EWR   JFK   LGA  
##    <chr> <chr> <chr> <chr>
##  1 ALB   00:32 <NA>  <NA> 
##  2 ANC   06:53 <NA>  <NA> 
##  3 ATL   01:52 01:52 01:54
##  4 AUS   03:31 03:34 <NA> 
##  5 AVL   01:30 <NA>  01:32
##  6 BDL   00:25 <NA>  <NA> 
##  7 BNA   01:55 01:57 01:54
##  8 BOS   00:40 00:38 00:38
##  9 BQN   03:16 03:14 <NA> 
## 10 BTV   00:46 00:47 00:43
## # ℹ 94 more rows
  • Xác định thời gian bay trung bình lâu nhất và ngắn nhất.
subset(avgtime, mean_air_time == max(mean_air_time))
## # A tibble: 1 × 4
## # Groups:   origin [1]
##   origin dest  mean_air_time     n
##   <chr>  <chr> <chr>         <int>
## 1 JFK    HNL   10:23           342
subset(avgtime, mean_air_time == min(mean_air_time))
## # A tibble: 1 × 4
## # Groups:   origin [1]
##   origin dest  mean_air_time     n
##   <chr>  <chr> <chr>         <int>
## 1 EWR    BDL   00:25           412

Đường bay có thời gian bay trung bình lâu nhất là từ EWR đến HNL với 10 tiếng 23 phút.

Đường bay có thời gian bay trung bình ngắn nhất là từ EWR đến DBL với 25 phút.

  • Tìm hiểu mối quan hệ giữa thời gian bay và khoảng cách.
# Chia cột distance (khoảng cách) thành 4 khoảng từ 80-1306 , 1306-2532 , 2531-3758 , 3758-4984 và gán vào biến dis
f1$dis <- cut(f1$distance, breaks =c(79,1306,2532,3758,4984), labels =c('80-1306', '1306-2532', '2532-3758', '3758-4984'), na.rm =TRUE)

# Phân nhóm dữ liệu theo biến dis và tính trung bình biến air_time 
dis_air <- f1 %>%  group_by(dis) %>% summarise(mean_air_time = mean(air_time))

Tương tự ở phần trên, ta cũng sử dụng hms() và substr() để đổi số phút thành định dạng giờ:phút

dis_air$mean_air_time <- substr(as.character(hms::round_hms(hms::hms(minutes = dis_air$mean_air_time), secs = 60)),1,5)

ggplot(dis_air, aes(x=dis, y = mean_air_time))+
  geom_col(na.rm = TRUE, fill = 10)+
  labs(x= 'Khoảng cách', y='Thời gian bay trung bình')

Ta thấy, khoảng cách càng lớn thì thời gian bay trung bình càng tăng.

4 CHƯƠNG IV Kết luận

4.1 Kết luận liên quan đến chủ đề

Gói “lubridate” là một gói rất hữu ích để làm việc với dữ liệu thời gian và ngày tháng trong R. Nhưng không có cái gì là toàn vẹn, nó cũng mang lại các ưu ngược điểm khác nhau cho mình.

Ưu điểm:

  1. Cú pháp dễ hiểu: Gói “lubridate” cung cấp cú pháp dễ hiểu và trực quan cho việc làm việc với dữ liệu thời gian, giúp cho việc xử lý dữ liệu trở nên dễ dàng hơn.

  2. Xử lý định dạng phổ biến: Gói này hỗ trợ xử lý định dạng ngày tháng phổ biến như “yyyy-mm-dd” hay “dd/mm/yyyy” một cách linh hoạt và tiện lợi.

  3. Tính năng mạnh mẽ: Gói “lubridate” cung cấp nhiều hàm và công cụ mạnh mẽ để thực hiện các tác vụ phổ biến liên quan đến xử lý và tính toán dữ liệu thời gian, như trích xuất thông tin về ngày, tháng, năm, tạo ra đối tượng ngày hay thời gian, tính toán khoảng cách thời gian, và nhiều hơn nữa.

  4. Tương thích với gói dplyr và tidyr: Gói “lubridate” tương thích tốt với gói “dplyr” và “tidyr”, giúp cho việc xử lý dữ liệu thời gian cùng với các tác vụ khác trở nên thuận tiện và linh hoạt hơn.

Nhược điểm:

  1. Khả năng xử lý dữ liệu lỗi: Gói “lubridate” có thể gặp khó khăn khi xử lý và chuyển đổi đối tượng thời gian có chứa dữ liệu lỗi hay không chuẩn. Điều này đòi hỏi người dùng phải cẩn thận và kiểm tra dữ liệu trước khi tiến hành xử lý.

  2. Hiệu suất tính toán: Do cung cấp nhiều tính năng mạnh mẽ, gói “lubridate” có thể có hiệu suất tính toán chậm hơn so với một số gói khác, đặc biệt đối với tập dữ liệu lớn.

  3. Hạn chế trong việc làm việc với múi giờ: Gói “lubridate” có thể gặp khó khăn khi làm việc với dữ liệu thời gian có liên quan đến múi giờ khác nhau. Đặc biệt là việc xử lý và chuyển đổi dữ liệu thời gian theo múi giờ không đồng nhất có thể khá phức tạp.

Mặc dù gói “lubridate” có một số nhược điểm như đã đề cập ở trên, nó vẫn là một công cụ rất hữu ích để làm việc với dữ liệu thời gian và ngày tháng trong R.

4.2 Kết luận trong quá trình làm chủ đề

Trong quá trình làm chủ đề tìm hiểu package lubridate của mình chúng em hiểu và học được nhiều hơn về các khía cạnh về thời gian trong R . Biết thêm được những ứng dụng khác cũng tự như package thú vị này. Mọi thứ đều có các quy luật các công thức riêng của mình và tầm quan trọng của gói này mang lại trong các lĩnh vực khác nhau.

Nhóm chúng em thấy rõ được sự hỗ trợ mạnh mẽ của công cụ R kết hợp với các dữ kiện mang tính thời gian tron cuộc sống. Nhóm em đúc kết được những cơ hội cũng như khó khăn trong việc sử dụng package lubridate của R - studio.

Những lợi ích mà package đem lại khá nhiều hơn so với bất lợi mà nó đem lại. Trong số các gói packages trước đó dùng để xử lý các vấn đề liên quan đến thời hầu như có sự khó nhằn hơn so với package lubridate đem lại. Trong quá trính tìm hiểu về package này nhóm em nhận lại được rất nhiều thứ không chỉ riêng về cách sử dụng packages mà còn hiểu nhiều hơn về cách kết hợp giữa thời gian và trực quan hóa dữ liệu.

Tùy theo kiểu dữ liệu mà đem lại cho chúng ta các nhìn nhận khác nhau về dữ liệu. Cách diễn đạt ngày giờ phút giây lên thành hình ảnh. Làm cho chúng sinh động như cách cuộc sống diễn ra.