Lấy và làm sạch dữ liệu với R: Ngày và Thời gian với lubridate

Watch

Watch


Trong bài viết này, ta sẽ khảo sát lubridate R package được phát triển bởi Garrett Grolemund và Hadley Wickham.  Theo tác giả đề cập, “lubridate có cú pháp đồng nhất và dễ nhớ giúp cho thao tác trên dữ liệu Ngày và Thời gian thêm thú vị thay vì bực dọc”. Nếu bạn đã từng làm việc với Ngày và Thời gian thì phát biểu trên sẽ khiến bạn chú ý.

Chúng ta hãy bắt đầu bằng việc load lubridate vào không gian làm việc.

library(lubridate)
help(package = lubridate)

Hàm today() trả về ngày hiện tại. Chúng ta sẽ lưu nó vào biến this_day.

this_day <- today()
this_day
[1] "2015-07-17"

Có ba thành phần trong biến this_date. Theo thứ tự năm, tháng, ngày. Chúng ta có thể rút trích thông tin này qua hàm year(), month(), day().

# lấy thông tin tháng 
month(this_day)
[1] 7

# lấy thông tin thứ
wday(this_day)
[1] 6
wday(this_day, label = TRUE)
[1] Fri
Levels: Sun < Mon < Tues < Wed < Thurs < Fri < Sat

Ngoài ra, lubridate là thư viện tuyệt vời để làm việc với Ngày và Thời gian đồng thời với nhau. Hàm now() trả về Ngày-Thời gian biểu diễn thời điểm hiện tại. Chúng ta sẽ lưu thời điểm này vào biến this_moment.

this_moment <- now()
this_moment
[1] "2015-07-17 08:37:18 JST"

Cũng như kiểu dữ liệu Ngày, ta có thể rút trích thông tin năm, tháng, ngày hay thứ. Tuy nhiên, chúng ta cũng có thể rút trích thông tin giờ, phút, giây.

second(this_moment)
[1] 18.29762

lubridate còn cung cấp những hàm khác nhau liên quan đến việc phân rã (parsing) date-times. Những hàm này có dạng ymd(), dmy(), hms(), ymd_hms(). Trong đó, mỗi kí tự viết tắt cho năm (y), tháng (m), ngày (d), giờ (h), phút (m), giây (s).

my_date <- ymd("1989-05-17")
my_date
[1] "1989-05-17 UTC"

# kiểm tra kiểu dữ liệu của my_date
class(my_date)
[1] "POSIXct" "POSIXt"

Kết quả tương tự như trên chỉ trừ ta có thêm thông tin time zone (UTC). Hàm ymd() lấy đầu vào là character string sau đó trả về đối tượng thuộc lớp POSIXct. Đây là cách mà R lưu trữ thông tin date-time trong hệ thống.

“1989-05-17” là một định dạng khá chuẩn, nhưng lubridate đủ “thông minh” để nhận diện ra những định dạng date-time khác. Ta thử dùng hàm ymd() để phân rã “1989 May 17”.

ymd("1989 May 17")
[1] "1989-05-17 UTC"

Bất chấp định dạng khác nhau, cả hai đều bắt đầu với thông tin là năm, sau đó đến thông tin tháng, và ngày. Vì vậy, ta có thể dùng hàm ymd() để phân rã. Tương tự, ta có thể thực hiện với các định dạng sau:

mdy("March 12, 1975")
[1] "1975-03-12 UTC"

# 25081985 biểu diễn ngày 25 tháng 8 năm 1985
dmy(25081985)
[1] "1985-08-25 UTC"

# R có thể bị nhầm lần. Do đó, cần cẩn trọng khi truyền đối số
ymd("192012")
[1] NA
Warning message:
All formats failed to parse. No formats found.

# sửa lại dòng lệnh trên
ymd("1920/1/2")
[1] "1920-01-02 UTC"

# lưu thông tin giờ phút giây
hms("03:22:14")
[1] "3H 22M 14S"

Ta có thông tin dt1 như sau:

dt1
[1] "2014-08-23 17:23:02"

# phân rã thông tin dt1
ymd_hms(dt1)
[1] "2014-08-23 17:23:02 UTC"

lubridate còn có khả năng làm việc trên vectors Ngày, rất hữu dụng khi bạn cần phân rã thông tin của một cột dữ liệu. Ta tạo biến dt2 có thông tin như sau:

dt2
[1] "2014-05-14" "2014-09-22" "2014-07-11"
# phân rã thông tin dt2 
ymd(dt2)
[1] "2014-05-14 UTC" "2014-09-22 UTC" "2014-07-11 UTC"

Hàm update() cho phép chúng ta cập nhật một hay nhiều thành phần của date-time. Ví dụ, ta muốn cập nhật thông tin 08:34:55 (hh:mm:ss) cho biến this_moment ban nãy như sau:

update(this_moment, hours = 8, minutes = 34, seconds = 55)
this_moment
[1] "2015-07-17 08:57:24 JST"

# cập nhật biến this_moment
this_moment <- update(this_moment, hours = 10, minutes = 16, seconds = 0)
this_moment
[1] "2015-07-17 10:16:00 JST"

Bây giờ, giả sử bạn đang ở thành phố New York và bạn đang lập kế hoạch để thăm một người bạn ở Hong Kong. Có vẻ như bạn đã đánh mất lịch trình của mình, nhưng bạn biết rằng chuyến bay của mình rời New York vào lúc 17:34 (5:34pm). Đồng thời, bạn cũng biết rằng chuyến bay của mình sẽ đến Hong Kong sau 15 giờ 50 phút sau khi cất cánh.

Hãy tạo lại lịch trình của mình từ những gì bạn nhớ, bắt đầu với ngày và giờ khởi hành. Giả sử sau hay ngày nữa là tới ngày bay, chúng ta sẽ cộng thêm 2 ngày sau đó đặt thời điểm là lúc 17:34.

Để xác định ngày hiện tại ở New York, chúng ta sẽ sử dụng hàm now() một lần nữa. Lần này, chúng ta sẽ thêm thông tin time zone “America/New_York”. Sau đó, lưu kết quả vào biến gọi là nyc. Để biết được tất cả time zone được sử dụng trong lubridate, bạn có thể truy cập vào trang Wikipedia: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones.

nyc <- now("America/New_York")
nyc
[1] "2015-07-16 21:44:59 EDT"

Chuyến bay của bạn là ngày mốt (theo giờ New York), vì vậy chúng ta sẽ thêm hai ngày vào biến nyc. Một đặc điểm nổi bật của lubridate đó là nó cho phép bạn sử dụng các toán tử số học lên Ngày và Giờ.

depart <- nyc + days(2)
depart 
[1] "2015-07-18 21:44:59 EDT"

Hiện tại biến depart đã lưu gía trị hai ngày tiếp theo. Ta sử dụng hàm udpate() để cập nhật số giờ là (17) và số phút là (34) vào lịch cất cánh.

depart <- update(depart, hours = 17, minutes = 34)
depart
[1] "2015-07-18 17:34:59 EDT"

Người bạn của chúng ta muốn biết mấy giờ thì cô ấy có thể đến đón bạn ở sân bay Hong Kong. Hiện tại, chúng ta đã biết chính xác ngày và giờ bạn cất cánh từ New York, chúng ta tìm cách xác định thời điểm bạn đến Hong Kong.

Bước một là cộng thêm 15 giờ 50 phút vào thời điểm cất cánh.

arrive <- depart + hours(15) + minutes(50)
arrive
[1] "2015-07-19 09:24:59 EDT"

Biến arrive chứa thông tin thời điểm sau khi bạn xuất phát từ New York đến Hong Kong. Điều chúng ta cần biết đó là giờ ở Hong Kong khi bạn đáp cánh để người bạn của chúng ta có thể đến đón.

Hàm with_tz() sẽ trả về giá trị ngày giờ ở time zone khác.

arrive <- with_tz(arrive, "Asia/Hong_Kong")
arrive
[1] "2015-07-19 21:24:59 HKT"

Ngay sau khi đến Hong Kong. Bạn và người bạn của mình vừa gặp nhau tại sân bay thì bạn nhận ra rằng lần cuối hai người gặp nhau là ở Singapore vào June 17, 2008. Một cách tự nhiên, bạn sẽ muốn biết khoảng thời gian đó đã bao lâu rồi.

Sử dụng hàm lubridate để phân rã “June 17, 2008” và có kèm theo thông tin time zone ở Singapore.

last_time <- mdy("June 17, 2008", tz = "Singapore")
last_time
[1] "2008-06-17 SGT"

Chúng ta sẽ dùng hàm new_interval() để xác định khoảng thời gian giữa thời điểm hiện tại và lần gặp trước đó.

how_long <- new_interval(last_time, arrive)
how_long
[1] 2008-06-17 SGT--2015-07-19 21:24:59 SGT

# xem khoảng thời gian là bao lâu
as.period(how_long)
[1] "7y 1m 2d 21H 24M 59.7429351806641S"

Nhờ có lubridate mà ta có thể bỏ qua các bước tính toán phức tạp rất dễ gây sai sót trong quá trình phân tích.

Nguồn tham khảo: http://swirlstats.com/

Advertisements

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Đăng xuất / Thay đổi )

Connecting to %s