Thao tác cơ bản với khung dữ liệu trong R (phần 2)

Giới thiệu

    R là một ngôn ngữ lập trình bậc cao, nó được tạo ra với mục đích dành cho các công việc phân tích dữ liệu, thống kê và học máy. Tôi gọi R là "Super Excel" và nó còn hơn thế nữa. Trong phần trước tôi đã giới thiệu một số thao tác cơ bản với khung dữ liệu (data frame) (https://viblo.asia/p/thao-tac-co-ban-voi-khung-du-lieu-trong-r-phan-1-4P856rGW5Y3). Hãy cùng tìm hiểu thêm về chủ đề này trong bài viết này.

Thực hành trên dữ liệu nào?

    R có rất nhiều tập dữ liệu cho chúng ta thực hành các câu lệnh, bạn có thể xem danh sách các tập dữ liệu sẵn có bằng hàm data(). Tuy nhiên trong bài này tôi sẽ thao tác trên tập dữ liệu "titanic", mặc dù nó cũng là một tập dữ liệu khá nổi tiếng tuy nhiên không có sẵn trong R. Có nhiều cách để thêm tập dữ liệu này, dưới đây tôi sẽ cài đặt thư viện "titanic", rồi khai báo sử dụng thư viện này và sau đó chúng ta có thể sử dụng tập dữ liệu "titanic":

> install.packages("titanic")
> library(titanic)
> head(titanic_train)
  PassengerId Survived Pclass                                                Name    Sex Age SibSp Parch           Ticket    Fare Cabin Embarked
1           1        0      3                             Braund, Mr. Owen Harris   male  22     1     0        A/5 21171  7.2500              S
2           2        1      1 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female  38     1     0         PC 17599 71.2833   C85        C
3           3        1      3                              Heikkinen, Miss. Laina female  26     0     0 STON/O2. 3101282  7.9250              S
4           4        1      1        Futrelle, Mrs. Jacques Heath (Lily May Peel) female  35     1     0           113803 53.1000  C123        S
5           5        0      3                            Allen, Mr. William Henry   male  35     0     0           373450  8.0500              S
6           6        0      3                                    Moran, Mr. James   male  NA     0     0           330877  8.4583              Q

    hàm head() hiển thị sáu quan sát của khung dữ liệu được truyền vào. Tương tự hàm head() là hàm tail(), nó hiển thị sáu quan sát cuối cùng.

    Data frame có cấu trúc giống bảng tính gồm các quan sát (observation) và các biến (variable), ở đây tôi sẽ dùng thuật ngữ "quan sát" đại diện cho một dòng và "biến" đại diện cho cột.

Thực hành

Truy vấn dữ liệu con

    Nhu cầu phổ biến nhất trong thao tác dữ liệu là chọn ra những dữ liệu mà người phân tích quan tâm, có thể là các biến hoặc các quan sát thỏa mãn điều kiện nào đó. R là một ngôn ngữ mạnh mẽ và nó làm điều này một cách hết sức đơn giản.

    Chọn các biến

    Cú pháp chung là: dataframe[row indices, column indices], nếu muốn lấy toàn bộ các quan sát chúng sẽ để trống phần row indices:

> x <- titanic_train[ , 'Name']
> head(x)
[1] "Braund, Mr. Owen Harris"                            
[2] "Cumings, Mrs. John Bradley (Florence Briggs Thayer)"
[3] "Heikkinen, Miss. Laina"                             
[4] "Futrelle, Mrs. Jacques Heath (Lily May Peel)"       
[5] "Allen, Mr. William Henry"                           
[6] "Moran, Mr. James"  

    Các câu lệnh sau sẽ làm điều tương tự với câu lệnh trên: titanic_train['Name'] hoặc titanic_train$Name.

    Hoặc truy vấn nhiều hơn một biến:

> y <- titanic_train[ , c('Name', 'Age')]
> head(y)
                                                Name      Age
1                             Braund, Mr. Owen Harris 22.00000
2 Cumings, Mrs. John Bradley (Florence Briggs Thayer) 38.00000
3                              Heikkinen, Miss. Laina 26.00000
4        Futrelle, Mrs. Jacques Heath (Lily May Peel) 35.00000
5                            Allen, Mr. William Henry 35.00000
6                                    Moran, Mr. James 29.69912

    Tương tự, câu lệnh titanic_train[c('Name', 'Age')] cũng có ý nghĩa giống câu lệnh trên.

    Lọc điều kiện

    Hãy xem một ví dụ:

> x <- titanic_train[titanic_train$Sex=='male' & titanic_train$Age > 30, ]
> head(x)
   PassengerId Survived Pclass                        Name  Sex Age SibSp Parch   Ticket    Fare Cabin Embarked
5            5        0      3    Allen, Mr. William Henry male  35     0     0   373450  8.0500              S
7            7        0      1     McCarthy, Mr. Timothy J male  54     0     0    17463 51.8625   E46        S
14          14        0      3 Andersson, Mr. Anders Johan male  39     1     5   347082 31.2750              S
21          21        0      2        Fynney, Mr. Joseph J male  35     0     0   239865 26.0000              S
22          22        1      2       Beesley, Mr. Lawrence male  34     0     0   248698 13.0000   D56        S
31          31        0      1    Uruchurtu, Don. Manuel E male  40     0     0 PC 17601 27.7208              C

    Bây giờ kết hợp giữa việc lọc điều kiện và chọn ra các biến mong muốn:

> y <- titanic_train[titanic_train$Sex=='male' & titanic_train$Age > 30, c('Name', 'Age', 'Fare')]
> head(y)
                         Name Age    Fare
5     Allen, Mr. William Henry  35  8.0500
7      McCarthy, Mr. Timothy J  54 51.8625
14 Andersson, Mr. Anders Johan  39 31.2750
21        Fynney, Mr. Joseph J  35 26.0000
22       Beesley, Mr. Lawrence  34 13.0000
31    Uruchurtu, Don. Manuel E  40 27.7208

Thống kê cơ bản

    Có bao nhiêu hành khách

    Số hành khách chính là số quan sát của khung dữ liệu:

> nrow(titanic_train)
[1] 891

    Vậy trong khung dữ liệu titanic_train có 891 quan sát tương ứng với 891 hành khách.

    **Giá vé trung bình là bao nhiêu **

> mean(titanic_train$Fare)
[1] 32.20421

    Độ tuổi trung bình

> mean(titanic_train$Age)
[1] NA

    Trong trường hợp này R không tính được trung bình của biến "Age". Câu hỏi là tại sao lại như vậy ? Là do trong biến này có giá trị chưa xác định (missing value), vì vậy chúng ta sẽ không tính toán với các quan sát chứa missing value.

> mean(titanic_train$Age, na.rm=TRUE)
[1] 29.69912

    Nhân tiện tôi đã kiểm tra có 177 quan sát xảy ra missing value với biến "Age":

> sum(is.na(titanic_train$Age))
[1] 177

Missing values

    Để kiểm tra missing value ta sử dụng hàm is.na() :

> x <- c('a', 'b', NA, 'd', 'e', NA)
> is.na(x)
[1] FALSE FALSE  TRUE FALSE FALSE  TRUE

    Bạn hãy tự thử với câu lệnh is.na(titanic_train). Thậm chí ta có thể truyền cả một khung dữ liệu vào hàm is.na(). R thật là "mạnh" !

    Bây giờ hãy "lấp các khoảng trống", Một số mô hình học máy không hoạt động được nếu có missing value trong khung dữ liệu, chúng ta sẽ thay các giá trị missing value trong biến "Age" bằng giá trị trung bình của chính nó:

> age.mean = mean(titanic_train$Age, na.rm=TRUE)
> titanic_train$Age[is.na(titanic_train$Age)] = age.mean

Sắp xếp dữ liệu

    Tôi có một câu hỏi: "Số phận của những người trả vé cao hoặc thấp cho chuyến đi đã ra sao?". Để trả lời câu hỏi này, tôi sẽ sắp xếp dữ liệu theo biến "Fare" (giá vé)

> new.data = titanic_train[order(titanic_train$Fare), ]
> head(new.data)
    PassengerId Survived Pclass                            Name  Sex      Age SibSp Parch Ticket Fare Cabin Embarked
180         180        0      3             Leonard, Mr. Lionel male 36.00000     0     0   LINE    0              S
264         264        0      1           Harrison, Mr. William male 40.00000     0     0 112059    0   B94        S
272         272        1      3    Tornquist, Mr. William Henry male 25.00000     0     0   LINE    0              S
278         278        0      2     Parkes, Mr. Francis "Frank" male 29.69912     0     0 239853    0              S
303         303        0      3 Johnson, Mr. William Cahoone Jr male 19.00000     0     0   LINE    0              S
414         414        0      2  Cunningham, Mr. Alfred Fleming male 29.69912     0     0 239853    0              S

    Thứ tự sắp xếp mặc định là tăng dần, vì vậy ở câu lệnh trên chúng ta đã quan sát thấy sáu hành khách có giá vé thấp nhất. Còn những người trả vé cao nhất thì sao:

> new.data2 = titanic_train[order(-titanic_train$Fare), ]
> head(new.data2)
    PassengerId Survived Pclass                               Name    Sex Age SibSp Parch   Ticket     Fare       Cabin Embarked
259         259        1      1                   Ward, Miss. Anna female  35     0     0 PC 17755 512.3292                    C
680         680        1      1 Cardeza, Mr. Thomas Drake Martinez   male  36     0     1 PC 17755 512.3292 B51 B53 B55        C
738         738        1      1             Lesurer, Mr. Gustave J   male  35     0     0 PC 17755 512.3292        B101        C
28           28        0      1     Fortune, Mr. Charles Alexander   male  19     3     2    19950 263.0000 C23 C25 C27        S
89           89        1      1         Fortune, Miss. Mabel Helen female  23     3     2    19950 263.0000 C23 C25 C27        S
342         342        1      1     Fortune, Miss. Alice Elizabeth female  24     3     2    19950 263.0000 C23 C25 C27        S

    Thật đơn giản đến bất ngờ, hầu như không có sư khác nhau giữa hai đoạn code trên, sự khác biệt duy nhất là tôi đã thêm dấu "trừ" trong hàm order(-titanic_train$Fare). Bạn hãy tự đưa ra nhận xét của mình: những người trả tiền cao thì sao, những người trả tiền thấp nhất thì sao?

Nguồn: Viblo

Bình luận
Vui lòng đăng nhập để bình luận
Một số bài viết liên quan