# A tibble: 6 × 13
ID_TRIP CAT_DESTINATION_CITY DT_START DT_END N_DURATION_DAY CAT_TRAVELER_NAME
<dbl> <chr> <chr> <chr> <dbl> <chr>
1 1 London, UK 5/1/2023 5/8/2… 7 John Smith
2 2 Phuket, Thailand 6/15/2023 6/20/… 5 Jane Doe
3 3 Bali, Indonesia 7/1/2023 7/8/2… 7 David Lee
4 4 New York, USA 8/15/2023 8/29/… 14 Sarah Johnson
5 5 Tokyo, Japan 9/10/2023 9/17/… 7 Kim Nguyen
6 6 Paris, France 10/5/2023 10/10… 5 Michael Brown
# ℹ 7 more variables: VAL_AGE_TRAVELER <dbl>, IND_GENDER_TRAVELER <chr>,
# CAT_TRAVELER_NATIONALITY <chr>, CAT_ACCOMMODATION_TYPE <chr>,
# AMT_ACCOMMODATION_COST <chr>, CAT_TRANSPORTATION_TYPE <chr>,
# AMT_TRANSPORTATION_COST <chr>
Các bạn cũng có thể xem thêm slide về dbtplyr của Emily trong posit::conf ở đây.
Đây là keynote từ article Column Names as Contracts của Emily Riederer.
Các sản phẩm phần mềm luôn tuân theo một quy ước nhất định (về hình ảnh, ký tự) nhằm để người dùng có thể ngay lập tức nắm bắt được cách thức sử dụng, giao tiếp với nó. Ví dụ, nút Home thường sẽ đưa người dùng về trang chủ của một mobile app, nút “blog” trên blog của tôi sẽ đưa các bạn tiếp cận danh mục bài viết, etc. Ở layer phía sau, các API được BE viết cần tuân thủ documented inputs & outputs, để các BE khác hay FE có thể sử dụng.
Tuy nhiên các bảng dữ liệu lại nằm ở một vùng màu xám không rõ ràng. Data service (từ producer i.e DE -> user i.e DA, DS) đủ tĩnh để không được xem là normal service, nhưng cũng đủ thô để người ta ít chú ý đến nó về mặt giao diện. DE cứ thể lấy hết mọi dữ liệu trong hệ thống, DA nhìn dữ liệu và ngay lập tức giả định được nội dung của (cột) dữ liệu đó.
Producers wonder why consumers aren’t satisfied, and consumers wonder why the data is never “right”.
Cũng có một cách được nhiều tổ chức sử dụng như là Metadata managament, như:
Tuy nhiên giải pháp này là documentation oriented, producer và user đều phải tuân thủ nghiêm ngặt. Nó không trực diện khi DE đặt tên cột, hay DA đọc dữ liệu.
Ý tưởng của Emily là chuẩn hóa các quy ước đặt tên dữ liệu bằng Controlled vocabulary. Minh họa bằng pointblank
, collapsibleTree
, và dplyr
.
Controlled Vocabulary
CV là phương pháp sử dụng một tập hợp các từ, cụm từ, từ viết tắt để ký hiệu thông tin. Quy ước này cần được định nghĩa đề phù hợp cho tính chất bộ dữ liệu, và cũng đủ đơn giản để người tạo dữ liệu, người sử dụng dữ liệu sử dụng.
Ví dụ, 1 ứng dụng booking.
Level 1: Kiểu dữ liệu, kiểu đo lường
ID
: chỉ đối tượng, dạng numberic, tối ưu cho việc lưu trữ và thường làm khóa chính các bảng’IND
: giá trị boolean 0/1, tôi thì thường sử dụng các từ nhưIS
,FLAG
;N
: chỉ các dạng thông tin có thể đếm (count) được;AMT
: chỉ các dạng thông tin có thể tổng, thường đề cập đến currency;VAL
: cũng là số nhưng không thể tổng được (không có ý nghĩa), ví dụ như kinh độ, vĩ độ;DT
: ngày;TM
: giờ hoặc ngày giờ;CAT
: category
Cũng tùy vào dữ liệu, có thể thêm các cụm từ nhất định đề đề cập đến thông tin dữ liệu đó mang lại, ví dụ ADD
cho address.
Level 2: Đối tượng, chủ đề
Mối quan tâm của người dùng dữ liệu cũng giống như nhà quản trị, xung quanh các đối tượng của business: USER
, TRANSACTION
, etc.
Đối với ứng dụng đặt xe, các chủ thể có thể cần quan tâm là TRIP
, TRAVELER
, ACCOMODATION
, TRANSPORTATION
, etc.
Level 3-n: Chi tiết
Hai tầng trên về cơ bản đã cho phép chúng ta mô tả được cột thông tin, chúng đều thể hiện được thuộc tính của chủ thể. Ví dụ:
AMT_TRIP
: giá trị deal của Trip;ADD_DESTINATION
: Điểm đến của trip.
Tuy nhiên tùy vào từng use case, chúng ta hoàn toàn có thể mở rộng được về cả hai phía. Ví dụ:
- Về phía trước: khi làm việc với nhiều layer dữ liệu, ta có thể dùng
RAW
,STAGING
,DW
,DL
,DM
, etc
- Về phía sau:
DAY
hoặcMONTH
choN_DURATION
,VND
hoặcUSD
cho currencyAMT
.
Miễn là có một quy chuẩn, và nó đủ đơn giản để sử dụng.
Kết hợp chúng lại
Tất nhiên ràng buộc việc đặt tên như vậy không chỉ để trang trí, nó sẽ giúp chúng ta tự động hóa quy trình kiểm soát chất lượng dữ liệu, .
Tôi sử dụng bộ dữ liệu này để thực hành (cột dữ liệu đã được đổi tên).
Data Validation
Sử dụng pointblank
của R để kiếm tra một số tính chất của dữ liệu:
library(pointblank)
agent <-
trip_data %>%
create_agent(actions = action_levels(stop_at = 0.001)) %>%
col_vals_gte(starts_with("N"), 0) %>% # check if cols start with N is GTE 0 or not
col_vals_gte(starts_with("VAL"), 0) %>% # check if cols start with VAL is GTE 0 or not
col_vals_not_null(starts_with("IND")) %>% # check if cols start with IND contain Null or not
col_vals_in_set(starts_with("IND"), c("Male","Female")) %>% # validate the value of only column started with IND - Gender
col_is_date(starts_with("DT")) %>% # check validation of date columns
interrogate()
Cool! Không chỉ kiểm tra được tính đúng đắn của dữ liệu, cũng có thể xác định được biến nào không tuân theo quy tắc đặt tên.
Data Discoverability
cols_data <- names(trip_data)
cols_data_split <- strsplit(cols_data,"_")
cols_components <- data.frame(
variable = cols_data,
level1 = vapply(cols_data_split, FUN = function(x) x[1], FUN.VALUE = character(1)),
level2 = vapply(cols_data_split, FUN = function(x) x[2], FUN.VALUE = character(1))
)
head(cols_components)
variable level1 level2
1 ID_TRIP ID TRIP
2 CAT_DESTINATION_CITY CAT DESTINATION
3 DT_START DT START
4 DT_END DT END
5 N_DURATION_DAY N DURATION
6 CAT_TRAVELER_NAME CAT TRAVELER
Đây là một cách để xây dựng metadata, chúng ta có thể touch một cách interactive với:
Cũng có thể visualize thành một tree như bên dưới:
library(collapsibleTree)
collapsibleTree(cols_components,
hierarchy = paste0("level", 1:2),
nodeSize = "leafCount"
)
Đây là cách xem từ kiểu dữ liệu -> chủ thể, chúng ta cũng có thể làm ngược lại:
Bộ dữ liệu mình sử dụng khá nghèo nàn và tập trung về một chủ thể duy nhất là TRIP
, nên khả năng minh họa không được phong phú 😂. Ngoài ra, việc đặt tên như thế cũng giúp ta dễ dàng gọi biến ở IDE.
Data Wrangling
Tương tự, với việc sử dụng một bộ từ điển có hệ thống, lớp lang cũng support chúng ta trong việc biến đổi dữ liệu. Ví dụ chúng ta có thể tận dụng “select helpers” trong gói dplyr
:
library(dplyr)
trip_data <- as.data.frame(trip_data)
trip_data %>%
filter(if_any(everything(), ~ !is.na(.))) %>%
group_by(CAT_TRAVELER_NATIONALITY) %>%
summarize(
across(starts_with("DT_"), c(min,max))
)
# A tibble: 42 × 5
CAT_TRAVELER_NATIONALITY DT_START_1 DT_START_2 DT_END_1 DT_END_2
<chr> <chr> <chr> <chr> <chr>
1 American 1/1/2023 9/15/2022 1/1/2023 9/22/2022
2 Australian 11/20/2023 9/5/2022 11/30/2023 9/14/2022
3 Brazil 4/3/2024 4/3/2024 4/10/2024 4/10/2024
4 Brazilian 1/15/2024 8/1/2023 1/12/2024 8/10/2023
5 British 1/1/2025 8/20/2022 1/15/2023 9/2/2022
6 Cambodia 9/10/2022 9/10/2022 9/15/2022 9/15/2022
7 Canada 7/1/2022 9/1/2022 7/10/2022 9/10/2022
8 Canadian 1/2/2023 8/15/2023 1/9/2023 8/22/2023
9 China 5/8/2023 5/8/2023 5/14/2023 5/14/2023
10 Chinese 11/11/2022 9/1/2023 11/21/2022 9/8/2023
# ℹ 32 more rows
Other languages
Generating SQL
Sử dụng R để generate SQL query
Attaching package: 'dbplyr'
The following objects are masked from 'package:dplyr':
ident, sql
library(RSQLite)
df_mem <- memdb_frame(trip_data, .name = "example_table")
df_mem %>%
group_by(CAT_TRAVELER_NATIONALITY) %>%
summarize_at(vars(starts_with("N_")), mean, na.rm = TRUE) %>%
show_query()
<SQL>
SELECT `CAT_TRAVELER_NATIONALITY`, AVG(`N_DURATION_DAY`) AS `N_DURATION_DAY`
FROM `example_table`
GROUP BY `CAT_TRAVELER_NATIONALITY`
R - base
& data.table
sử dụng base::grep
để tìm tất cả các columns bắt đầu bằng AMT_
[1] "AMT_ACCOMMODATION_COST" "AMT_TRANSPORTATION_COST"
sử dụng vector để lưu các cột chúng ta muốn group by:
chúng ta có thể dùng vector này trong stats::aggregate
hoặc trong data.table
python pandas
tương tự trong python, sử dụng list comprehension:
Updates by Emily
Concept Map
New Package (Dec 2020)
convo
là một thư viện released bởi Emily phục vụ cho việc quản lý controlled vocabulary:
vocab.yaml
level1:
ID:
desc: Unique identifier
valid:
- col_vals_not_null()
- col_is_numeric()
- col_vals_between(1000, 99999)
IND:
desc: Binary indicator
valid:
- col_is_numeric()
- col_vals_in_set(c(0,1))
rename:
- when: SUM
then: 'N'
- when: AVG
then: P
AMT:
desc: Non-negative, summable quantity
valid:
- col_is_numeric()
- col_vals_gte(0)
VAL:
desc: Value
valid:
- col_is_numeric()
rename:
- when: AVG
then: VALAV
New Package (April 2021)
dbtplyr
là một package port tính năng “select helpers” của dplyr
sang dbt
.