Đề bài

Bạn có folder này chứa 332 file .csv tương ứng 332 cảm biến theo dõi chỉ tiêu sulfate và nitrate chất lượng nước ở các địa điểm khác nhau (số liệu mô phỏng, không có thực). Nguồn dataset từ Coursera/Data Science Specialization.

File .Rmd để render ở đây

https://tuhocr.netlify.app/code/project-coding-solution.Rmd

Download dataset https://tinyurl.com/4sm9ce76 sau đó giải nén ra folder specdata rồi đặt trong folder project R.

Cấu trúc 1 file .csv như sau:

data_020 <- read.csv("specdata/020.csv")
dim(data_020)
## [1] 1461    4
head(data_020)
##         Date sulfate nitrate ID
## 1 2002-01-01      NA      NA 20
## 2 2002-01-02      NA      NA 20
## 3 2002-01-03      NA      NA 20
## 4 2002-01-04      NA      NA 20
## 5 2002-01-05      NA      NA 20
## 6 2002-01-06      NA      NA 20

Câu 1

Ở dataset 020.csv có:

  1. bao nhiêu dòng, bao nhiêu cột

  2. bao nhiêu giá trị missing value ở cột sulfate

  3. bao nhiêu giá trị missing value ở cột nitrate

  4. bao nhiêu giá trị missing value ở cả 2 cột sulfatenitrate

  5. có bao nhiêu ngày quan sát nào có ĐỦ CẢ 2 giá trị theo dõi

  6. Tìm giá trị trung bình, max, min ở từng cột cho 2 trường hợp:

    1. loại missing value riêng từng cột

    2. loại missing value cho toàn bộ (tức là ở những cột có đủ 2 giá trị)

Làm sạch dataset 020.csv trước khi phân tích

# Import dataset
data_020 <- read.csv("specdata/020.csv")

# Kiểm tra dataset
sapply(data_020, class)
##        Date     sulfate     nitrate          ID 
## "character"   "numeric"   "numeric"   "integer"
str(data_020)
## 'data.frame':    1461 obs. of  4 variables:
##  $ Date   : chr  "2002-01-01" "2002-01-02" "2002-01-03" "2002-01-04" ...
##  $ sulfate: num  NA NA NA NA NA NA NA NA NA NA ...
##  $ nitrate: num  NA NA NA NA NA NA NA NA NA NA ...
##  $ ID     : int  20 20 20 20 20 20 20 20 20 20 ...
summary(data_020)
##      Date              sulfate          nitrate             ID    
##  Length:1461        Min.   : 0.472   Min.   :0.1080   Min.   :20  
##  Class :character   1st Qu.: 2.147   1st Qu.:0.3032   1st Qu.:20  
##  Mode  :character   Median : 3.180   Median :0.4740   Median :20  
##                     Mean   : 3.625   Mean   :0.7780   Mean   :20  
##                     3rd Qu.: 4.890   3rd Qu.:0.8140   3rd Qu.:20  
##                     Max.   :14.400   Max.   :6.7700   Max.   :20  
##                     NA's   :1337     NA's   :1333
# Chuyển cột `Date` character thành `Date` chuẩn vector ngày tháng
data_020$Date <- as.Date(data_020$Date, format = "%Y-%m-%d")
sapply(data_020, class) # kiểm tra lại class dataset 020.csv
##      Date   sulfate   nitrate        ID 
##    "Date" "numeric" "numeric" "integer"

1.a) bao nhiêu dòng, bao nhiêu cột

dim(data_020)
## [1] 1461    4

1.b) bao nhiêu giá trị missing value ở cột sulfate

# Cách 1: Nhìn từ kết quả của lệnh `summary`
summary(data_020$sulfate)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   0.472   2.147   3.180   3.625   4.890  14.400    1337
# Cách 2: Đếm trực tiếp NA dùng lệnh `sum(is.na(object))`
sum(is.na(data_020$sulfate))
## [1] 1337

1.c) bao nhiêu giá trị missing value ở cột nitrate

# Cách 1: Nhìn từ kết quả của lệnh `summary`
summary(data_020$nitrate)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##  0.1080  0.3032  0.4740  0.7780  0.8140  6.7700    1333
# Cách 2: Đếm trực tiếp NA dùng lệnh `sum(is.na(object))`
sum(is.na(data_020$nitrate))
## [1] 1333

1.d) bao nhiêu giá trị missing value ở cả 2 cột sulfatenitrate

length(intersect(which(is.na(data_020$sulfate)), which(is.na(data_020$nitrate))))
## [1] 1333

1.e) có bao nhiêu ngày quan sát nào có ĐỦ CẢ 2 giá trị theo dõi

# Cách 1: Tiếp cận theo cách làm phép cộng giữa 2 vector để tách ra giá trị `NA`
length(data_020$sulfate + data_020$nitrate) - sum(is.na(data_020$sulfate + data_020$nitrate))
## [1] 124
# Cách 2: Tiếp cận trực tiếp kiểm tra giá trị không phải là `NA` ở hai chỉ tiêu và CÓ GIAO NHAU
length(intersect(which(!is.na(data_020$nitrate)), which(!is.na(data_020$sulfate))))
## [1] 124

1.f) Tìm giá trị trung bình, max, min ở từng cột cho 2 trường hợp:

i) loại missing value riêng từng cột

# Cách 1: Làm thủ công
## sulfate
mean(data_020$sulfate, na.rm = TRUE)
## [1] 3.625065
max(data_020$sulfate, na.rm = TRUE)
## [1] 14.4
min(data_020$sulfate, na.rm = TRUE)
## [1] 0.472
## nitrate
mean(data_020$nitrate, na.rm = TRUE)
## [1] 0.7780469
max(data_020$nitrate, na.rm = TRUE)
## [1] 6.77
min(data_020$nitrate, na.rm = TRUE)
## [1] 0.108
# Cách 2: Áp dụng lệnh sapply
## tạo danh sách function để loop
funs <- list(gia_tri_trung_binh = mean, cuc_dai = max, cuc_tieu = min)
## trả về matrix kết quả cho cả hai chỉ tiêu

##### cách 2a):
sapply(funs, function(x) sapply(data_020[, 2:3], x, na.rm = TRUE))
##         gia_tri_trung_binh cuc_dai cuc_tieu
## sulfate          3.6250645   14.40    0.472
## nitrate          0.7780469    6.77    0.108
##### cách 2b):
sapply(funs, mapply, data_020[, 2:3], na.rm = TRUE)
##         gia_tri_trung_binh cuc_dai cuc_tieu
## sulfate          3.6250645   14.40    0.472
## nitrate          0.7780469    6.77    0.108

ii) loại missing value cho toàn bộ (tức là ở những cột có đủ 2 giá trị)

sapply(funs, function(x) sapply(na.omit(data_020)[, 2:3], x))
##         gia_tri_trung_binh cuc_dai cuc_tieu
## sulfate           3.625065   14.40    0.472
## nitrate           0.791371    6.77    0.108

Câu 2

Trong dataset này có hai chỉ tiêu sulfatenitrate được cảm biến đo độc lập nhau. Có những ngày ghi nhận được giá trị sulfate hoặc nitrate, có những ngày không ghi nhận giá trị gì cả (missing value), cũng như có ngày ghi nhận đầy đủ cả 2 giá trị sulfatenitrate.

Bạn hãy xây dựng function để tìm ra có bao nhiêu giá trị quan sát đầy đủ tương ứng ở từng cảm biến, để làm cơ sở đánh giá xem các cảm biến ở những vị trí khác nhau thì số lượng kết quả theo dõi có đồng đều nhau hay không.

# gọi function ra, đưa tham số là các dataset id cần tìm xem có bao nhiêu ngày có đầy đủ giá trị quan sát

# > complete("specdata", id = 18:22)

#    id  full_quan_sat
# 1 18   84
# 2 19  353
# 3 20  124 ← đây chính là kết quả câu 1e) khi tính thủ công
# 4 21  426
# 5 22  135

Cách 1: Function complete_1 tìm full giá trị quan sát, xây dựng theo cách tiếp cận for loop và gom lại thành data frame master, sau đó subset ra, tìm giá trị full_quan_sat bằng phép toán giữa các chỉ tiêu với NA (tương tự cách 1 ở câu 1e)

complete_1 <- function(directory = "specdata", id){
    
    files_list <- list.files(directory, full.names = TRUE)
    tmp <- files_list[id] # Đây là chỗ tùy chọn
    tmp_working <- vector(mode = "list", length = length(tmp))
    
    for (i in seq_along(tmp)) { 
        tmp_working[[i]] <- read.csv(tmp[[i]]) # Kiểu subset của tmp_working là dạng list tách ra dạng bảng
    }
    
    output_tmp_working <- do.call(rbind, tmp_working)
    
    y <- unique(output_tmp_working$ID) # Đếm số lần xuất hiện (number of occurences for each unique value)
    
    extract_data <- data.frame(matrix(ncol = 2, nrow = 0))
    
    for (uu in seq_along(y)) { 
        happy <- output_tmp_working[which(output_tmp_working[, "ID"] == y[uu]),]
        
        sul <- happy[,2]
        nit <- happy[,3]
        tot <- sul + nit
        sum(is.na(tot)) #Hàm đếm missing values trong vector  
        nobs <- length(tot) - sum(is.na(tot))
        extract_data <- rbind(extract_data, c(y[uu], nobs))
    }
    x <- c("cam_bien", "full_quan_sat")
    colnames(extract_data) <- x
    return(extract_data)
    
}

Test function complete_1

complete_1("specdata", id = 10:20)
##    cam_bien full_quan_sat
## 1        10           148
## 2        11           443
## 3        12            96
## 4        13            46
## 5        14            96
## 6        15            83
## 7        16            60
## 8        17           927
## 9        18            84
## 10       19           353
## 11       20           124

Cách 2: Function complete_2 tìm full giá trị quan sát, xây dựng theo cách tiếp cận sử dụng hàm apply, không gom lại thành data frame master mà chỉ dừng ở list master, khi cần subset thì gọi ra theo id, tìm giá trị full_quan_sat theo kiểu trực tiếp (tương tự cách 2 ở câu 1e)

complete_2 <- function(directory = "specdata", id){
    
    # import dataset
    files_list <- list.files(directory, full.names = TRUE,
                             pattern = ".csv") # set này để chọn riêng file .csv
    
    tmp_working <- lapply(files_list[id], read.csv) 
    
    # FUNCTION
    check_full_quan_sat <- function(check_id){
        
        raw <- tmp_working[[check_id]] 
        
        check_1 <- which(!is.na(raw$nitrate))
        check_2 <- which(!is.na(raw$sulfate))
        
        ra_soat <- intersect(check_1, check_2)
        
        length(ra_soat)
    }
    
    # sửa lại chỗ sapply seq_along(tmp_working)
    full_quan_sat <- sapply(seq_along(tmp_working), check_full_quan_sat)
    
    full_quan_sat <- as.data.frame(full_quan_sat)
    
    ket_qua <- cbind(cam_bien = id, full_quan_sat)
    
    return(ket_qua)
    
}

Test function complete_2

complete_2("specdata", id = 10:20)
##    cam_bien full_quan_sat
## 1        10           148
## 2        11           443
## 3        12            96
## 4        13            46
## 5        14            96
## 6        15            83
## 7        16            60
## 8        17           927
## 9        18            84
## 10       19           353
## 11       20           124

Kết quả từ cả hai function này trả về là y chang nhau.

identical(complete_1("specdata", id = 1:332),
          complete_2("specdata", id = 1:332))
## [1] TRUE

Xem thêm so sánh tốc độ hai function: https://www.tuhocr.com/blog/danh-gia-toc-do-function

Câu 3

Xây dựng function trả về kết quả mean ở từng chỉ tiêu theo giá trị id của mỗi dataset.

pollutantmean <- function(directory = "specdata", pollutant, id = 1:332) {
    
    # import dataset
    files_list <- list.files(directory, full.names = TRUE,
                             pattern = ".csv") # set này để chọn riêng file .csv
    
    tmp_working <- lapply(files_list[id], read.csv) 
    
    # gom chung 1 dataset
    output_tmp_working <- do.call(rbind, tmp_working)
    mean(output_tmp_working[, pollutant], na.rm = TRUE)
}

Test function pollutantmean

pollutantmean("specdata", "nitrate", 3:10)
## [1] 0.7471877
pollutantmean("specdata", "nitrate", 20)
## [1] 0.7780469
pollutantmean("specdata", "sulfate", 1:332)
## [1] 3.189369
pollutantmean("specdata", "sulfate", c(1:20, 50:110))
## [1] 3.484405

Câu 4

Liệt kê giá trị maxmin ở cả 2 chỉ tiêu ở các dãy cảm biến bất kỳ.

Đầu tiên, ta tận dụng lại hàm filter_theo_chi_tieu_super, đã xây dựng trước đây

https://www.tuhocr.com/huong-dan-cai-tien-function-step-by-step

Có hai cải tiến khi kế thừa function đã có và áp dụng trong bài này:

library(dplyr)

## FUNCTION_MIN_CHI_TIEU

"%min_chi_tieu%" <- function(a, b){
    
    # import dataset
    files_list <- list.files(b, full.names = TRUE)
    
    tmp_working <- vector(mode = "list", length = length(files_list))
    
    for(i in seq_along(files_list)) { 
        tmp_working[[i]] <- read.csv(files_list[i])
        tmp_working[[i]]$Date <- as.Date(tmp_working[[i]]$Date, format = "%Y-%m-%d")
        if(any(is.na(tmp_working[[i]]$Date))){
            tmp_working[[i]] <- read.csv(files_list[i])
            tmp_working[[i]]$Date <- as.Date(tmp_working[[i]]$Date, format = "%m/%d/%Y")    
        }
        
    }
    # find min value     
    
    ket_qua_min <- data.frame()
    
    for(min_i in seq_along(tmp_working)) { 
        
        if(chi_tieu %in% names(tmp_working[[min_i]])){
            
            gia_tri_min <- suppressWarnings(min(get(chi_tieu, tmp_working[[min_i]]), na.rm = TRUE))
            
            ### trích xuất ra vị trí index
            vi_tri <- which(get(chi_tieu, tmp_working[[min_i]]) == gia_tri_min)
            
            ket_qua_min <- bind_rows(ket_qua_min, tmp_working[[min_i]][vi_tri, ])
        }
        next
    }
    #### THÊM DÒNG THÔNG BÁO
    print(paste("Kết quả lọc theo giá trị MIN của", chi_tieu, "ở folder", b, "là:"))
    #### TRẢ KẾT QUẢ
    return(ket_qua_min)    
}    


## FUNCTION_MAX_CHI_TIEU

"%max_chi_tieu%" <- function(a, b){
    
    # import dataset
    files_list <- list.files(b, full.names = TRUE)
    
    tmp_working <- vector(mode = "list", length = length(files_list))
    
    for(i in seq_along(files_list)) { 
        tmp_working[[i]] <- read.csv(files_list[i])
        tmp_working[[i]]$Date <- as.Date(tmp_working[[i]]$Date, format = "%Y-%m-%d")
        if(any(is.na(tmp_working[[i]]$Date))){
            tmp_working[[i]] <- read.csv(files_list[i])
            tmp_working[[i]]$Date <- as.Date(tmp_working[[i]]$Date, format = "%m/%d/%Y")    
        }
    }
    # find max value     
    
    ket_qua_max <- data.frame()
    
    for(max_i in seq_along(tmp_working)) { 
        
        if(chi_tieu %in% names(tmp_working[[max_i]])){
            
            gia_tri_max <- suppressWarnings(max(get(chi_tieu, tmp_working[[max_i]]), na.rm = TRUE))
            
            ### trích xuất ra vị trí index
            vi_tri <- which(get(chi_tieu, tmp_working[[max_i]]) == gia_tri_max)
            
            ket_qua_max <- bind_rows(ket_qua_max, tmp_working[[max_i]][vi_tri, ])
        }
        next
    }
    #### THÊM DÒNG THÔNG BÁO
    print(paste("Kết quả lọc theo giá trị MAX của", chi_tieu, "ở folder", b, "là:"))
    #### TRẢ KẾT QUẢ
    return(ket_qua_max)    
}


### FUNCTION RANGE CHỈ TIÊU

"%range_chi_tieu%" <- function(a, b){
    
    # import dataset
    files_list <- list.files(b, full.names = TRUE)
    
    tmp_working <- vector(mode = "list", length = length(files_list))
    
    for(i in seq_along(files_list)){ 
        tmp_working[[i]] <- read.csv(files_list[i])
        tmp_working[[i]]$Date <- as.Date(tmp_working[[i]]$Date, format = "%Y-%m-%d")
        if(any(is.na(tmp_working[[i]]$Date))){
            tmp_working[[i]] <- read.csv(files_list[i])
            tmp_working[[i]]$Date <- as.Date(tmp_working[[i]]$Date, format = "%m/%d/%Y")    
        }
    }
    
    # tìm trong khoảng
    
    ket_qua_range <- data.frame()
    
    for(range_i in seq_along(tmp_working)){
        
        if(chi_tieu %in% names(tmp_working[[range_i]])) {
            
            ket_qua_tim_trong_khoang <- which(get(chi_tieu, tmp_working[[range_i]]) >= a[1] & 
            get(chi_tieu, tmp_working[[range_i]]) <= a[2])
            
            ket_qua_range <- bind_rows(ket_qua_range, tmp_working[[range_i]][ket_qua_tim_trong_khoang, ])
        }
        next
    }
    print(paste("Kết quả lọc trong khoảng, từ", a[1], "đến", a[2], "của", chi_tieu, "ở folder", b, "là:"))
    return(ket_qua_range ) 
} 

### function chung

"%chi_tieu%" <- function(a, b){
    
    if(length(a) == 1){
        switch(a, 
               "min" = a %min_chi_tieu% b, 
               "max" = a %max_chi_tieu% b)
    } else {
        a %range_chi_tieu% b
    }
    
}  

### FUNCTION FINAL

filter_theo_chi_tieu_enhanced <- function(chi_tieu = "mercury", a = "min", b = "2007"){
    chi_tieu <<- chi_tieu ### sử dụng super assign
    a %chi_tieu% b
}

##################

filter_theo_chi_tieu_super <- function(chi_tieu = "mercury", a = "min", b = "2007") {
    
    data_1 <- filter_theo_chi_tieu_enhanced(chi_tieu, a, b)
    if(length(data_1) != 0) {
        
        kq_sort <- sort(names(data_1)[!(names(data_1) %in% c("Date", "ID"))])
        
        ok <- c("Date", kq_sort, "ID")
        
        data_2 <- data_1[ok]
        
        return(data_2)  
        
    }
    
    return("Không có kết quả tìm kiếm")
    
}

Để thêm chức năng tìm theo id thì thay vì ta đưa câu lệnh vào trong hàm filter_theo_chi_tieu_super thì sẽ gây cồng kềnh. Ta sẽ làm 1 hàm mới là filter_theo_id, rồi nested hàm filter_theo_chi_tieu_super vào thì sẽ tiện hơn.

filter_theo_id <- function(chi_tieu = "sulfate", a = "max", b = "specdata", id_can_tim) {
    
    data_filter <- filter_theo_chi_tieu_super(chi_tieu, a, b)
    
    vi_tri <- which(get("ID", data_filter) %in% id_can_tim)
    
    ket_qua_chuan <- data_filter[vi_tri, ]
    
    return(ket_qua_chuan)
}

Test hàm filter_theo_id

filter_theo_id(chi_tieu = "sulfate", a = "max", b = "specdata", id = 280:332)
## [1] "Kết quả lọc theo giá trị MAX của sulfate ở folder specdata là:"
##           Date nitrate  sulfate  ID
## 285 2005-09-07      NA  6.33593 280
## 286 2000-10-21   0.256 18.00000 281
## 287 2000-10-24   0.687 15.20000 282
## 288 2000-10-24   0.849 16.30000 283
## 289 2002-09-14      NA 27.20000 284
## 290 2000-10-24   0.414 18.40000 285
## 291 2002-08-30      NA 14.80000 286
## 292 2000-10-24   0.899 16.30000 287
## 293 2002-08-29      NA 19.00000 288
## 294 2002-09-11      NA 19.00000 288
## 295 2005-08-02      NA  5.71843 289
## 296 2002-09-14      NA 24.80000 290
## 297 2002-08-30      NA 18.00000 291
## 298 2005-06-21      NA 10.23036 292
## 299 2005-04-16      NA  5.58111 293
## 300 2005-06-27      NA 12.27128 294
## 301 2000-10-21   0.688 12.40000 295
## 302 2002-08-30      NA 13.90000 296
## 303 2002-09-14      NA 19.20000 297
## 304 2002-12-10  15.100  8.69000 298
## 305 2004-01-22  16.400  4.71000 299
## 306 2001-01-04  18.700 14.60000 300
## 307 2004-01-16  31.300  5.79000 301
## 308 2001-07-24   0.284 18.80000 302
## 309 2007-08-07   0.257 20.50000 303
## 310 2006-08-03   0.567 14.50000 304
## 311 2003-06-26   1.340 22.80000 305
## 312 2001-08-08   0.251 24.70000 306
## 313 2002-07-01   1.400 23.80000 307
## 314 2009-08-23   0.340  2.35000 308
## 315 2004-11-05   3.240  3.50000 309
## 316 2002-10-23   3.230  3.89000 310
## 317 2001-08-17   0.619  3.22000 311
## 318 2004-12-17   2.740  5.30000 312
## 319 2004-12-17   2.800  5.18000 313
## 320 2004-10-03   3.470  4.95000 314
## 321 2006-07-04   0.748  3.67000 315
## 322 2009-01-19   1.920  3.52000 316
## 323 2009-08-17   0.760  2.20000 317
## 324 2007-11-20   1.870  2.44000 318
## 325 2007-11-23   3.180  2.61000 319
## 326 2007-08-04   0.226 20.70000 320
## 327 2007-08-04   0.618 19.20000 321
## 328 2005-06-27   0.330 25.50000 322
## 329 2010-01-14   2.390  5.56000 323
## 330 2010-03-09   9.000  5.21000 324
## 331 2005-06-27   1.850 22.20000 325
## 332 2005-08-02   1.280 22.80000 326
## 333 2002-09-29   3.950 12.20000 327
## 334 2005-08-02   1.010 23.90000 328
## 335 2005-08-02   0.698 12.60000 329
## 336 2005-06-27   1.470 20.50000 330
## 337 2002-08-03   0.249 10.20000 331
## 338 2004-04-09   0.150  2.94000 332
filter_theo_id(chi_tieu = "nitrate", a = "min", b = "specdata", id = 280:332)
## [1] "Kết quả lọc theo giá trị MIN của nitrate ở folder specdata là:"
##           Date nitrate sulfate  ID
## 284 2001-03-08  0.1480  1.9600 280
## 285 2000-08-29  0.0215  0.1540 281
## 286 2001-02-03  0.0751  0.3900 282
## 287 2000-09-14  0.0985  3.0500 283
## 288 2001-01-31  0.0867  0.2740 284
## 289 2000-11-02  0.1450 11.5000 285
## 290 2010-03-06  0.0516  0.0710 287
## 291 2010-01-26  0.0959  0.5300 288
## 292 2000-09-01  0.0228  0.0966 290
## 293 2000-09-26  0.0255  0.0774 295
## 294 2001-01-31  0.3050  1.6600 296
## 295 2001-04-25  0.2340  1.7600 297
## 296 2002-09-29  0.1090  0.5340 298
## 297 2008-08-16  0.0506  0.6130 299
## 298 2008-11-02  0.0447  0.0000 300
## 299 2005-11-06  0.0846  0.2790 301
## 300 2001-03-02  0.0000  0.1740 302
## 301 2007-05-12  0.0000  0.0473 302
## 302 2008-07-08  0.0000  0.0000 302
## 303 2009-04-07  0.0860  1.6600 303
## 304 2004-09-18  0.0779  0.7370 304
## 305 2005-06-03  0.0519  0.0341 305
## 306 2003-01-09  0.0601      NA 306
## 307 2003-12-11  0.1160  1.4100 307
## 308 2010-04-02  0.1340  0.3230 308
## 309 2002-07-19  0.1660  1.2300 309
## 310 2000-05-27  0.1308  0.3681 310
## 311 2002-12-10  0.2570      NA 311
## 312 2003-10-30  0.2020  0.6720 312
## 313 2009-07-06  0.0922  0.9490 313
## 314 2008-11-08  0.1110  0.2900 314
## 315 2006-03-06  0.0885  0.2600 315
## 316 2010-04-02  0.1030      NA 316
## 317 2010-04-02  0.0963  0.3670 317
## 318 2008-08-10  0.0550  0.7060 318
## 319 2008-04-30  0.0903  0.3470 319
## 320 2009-10-28  0.0719  2.0900 320
## 321 2009-06-30  0.1600  3.5600 321
## 322 2008-09-15  0.0979  1.2100 322
## 323 2009-10-10  0.1590  1.1100 323
## 324 2010-04-08  0.1600  0.4810 324
## 325 2009-07-12  0.0711  0.5270 325
## 326 2005-05-16  0.0768  0.6730 326
## 327 2004-07-02  0.1850  0.3640 327
## 328 2009-09-28  0.0653  0.5500 328
## 329 2009-07-06  0.0284      NA 329
## 330 2009-09-28  0.0828  0.5250 330
## 331 2005-12-27  0.1000  0.3280 331
## 332 2004-02-03  0.1250  0.4680 332
filter_theo_id(chi_tieu = "nitrate", a = c(0.667, 0.700), b = "specdata", id = c(12:14, 20:22))
## [1] "Kết quả lọc trong khoảng, từ 0.667 đến 0.7 của nitrate ở folder specdata là:"
##           Date nitrate sulfate ID
## 99  2004-05-27   0.692    1.34 12
## 100 2003-05-21   0.676    1.92 13
## 122 2002-11-10   0.680    3.48 20
## 123 2002-04-08   0.698    1.73 21
## 124 2003-03-28   0.694    1.67 21
## 125 2003-09-12   0.686    5.72 21
## 126 2003-10-30   0.669    3.01 21
## 127 2004-05-09   0.689    6.80 21
## 128 2005-04-16   0.675    6.21 21
## 129 2005-05-22   0.676    7.30 21
## 130 2007-05-24   0.667    4.40 21
## 131 2007-10-15   0.681    2.48 21
## 132 2008-06-11   0.680    2.53 21
## 133 2008-07-11   0.674    2.27 21
## 134 2009-12-27   0.674    1.21 21
## 135 2002-04-20   0.667    3.29 22
## 136 2002-05-02   0.688    3.02 22
## 137 2004-09-30   0.688    1.66 22
## 138 2004-12-29   0.690    4.75 22
## 139 2005-02-21   0.669    2.95 22
## 140 2005-04-16   0.681    6.29 22

Thực tế ở thời điểm này chúng ta có thể dùng lệnh merge() để ghép chung các dataset từ kết qua filter theo từng chỉ tiêu, tuy nhiên như vậy cũng còn hơi thủ công, do đó ta sẽ đưa lệnh merge() vào trong function mới là filter_theo_id_so_sanh để kết quả trả về sẽ đúng format mong muốn.

filter_theo_id_so_sanh <- function(chi_tieu_1, 
                                   chi_tieu_2,
                                   a, b, id_can_tim) {
    
    ok_1 <- filter_theo_id(chi_tieu = chi_tieu_1, a, b, id_can_tim)
    ok_2 <- filter_theo_id(chi_tieu = chi_tieu_2, a, b, id_can_tim)
    
    if(length(a) == 1) {
        ok_1$note <- paste(a[1], chi_tieu_1)
        ok_2$note <- paste(a[1], chi_tieu_2)
    } else {  
        ok_1$note <- paste("from", a[1], "to", a[2], chi_tieu_1)
        ok_2$note <- paste("from", a[1], "to", a[2], chi_tieu_2)
    }
    
    ok_1$sep <- "|"
    
    ket_qua_so_sanh <- merge(ok_1, ok_2, by = "ID", all = TRUE)
  
    return(ket_qua_so_sanh)
}

Test hàm filter_theo_id_so_sanh

options(digits = 2)
options(width = 200)
filter_theo_id_so_sanh(chi_tieu_1 = "sulfate", chi_tieu_2 = "nitrate", a = "max", b = "specdata", id_can_tim = 280:300)
## [1] "Kết quả lọc theo giá trị MAX của sulfate ở folder specdata là:"
## [1] "Kết quả lọc theo giá trị MAX của nitrate ở folder specdata là:"
##     ID     Date.x nitrate.x sulfate.x      note.x sep     Date.y nitrate.y sulfate.y      note.y
## 1  280 2005-09-07        NA       6.3 max sulfate   | 2001-01-01      9.76       2.6 max nitrate
## 2  281 2000-10-21      0.26      18.0 max sulfate   | 2000-11-20      2.05       2.1 max nitrate
## 3  282 2000-10-24      0.69      15.2 max sulfate   | 2001-02-04      3.81       2.4 max nitrate
## 4  283 2000-10-24      0.85      16.3 max sulfate   | 2001-02-03      2.97       3.6 max nitrate
## 5  284 2002-09-14        NA      27.2 max sulfate   | 2001-01-22      4.58       3.1 max nitrate
## 6  285 2000-10-24      0.41      18.4 max sulfate   | 2000-12-05      2.65       4.2 max nitrate
## 7  286 2002-08-30        NA      14.8 max sulfate   |       <NA>        NA        NA        <NA>
## 8  287 2000-10-24      0.90      16.3 max sulfate   | 2001-01-04      5.59       3.8 max nitrate
## 9  288 2002-08-29        NA      19.0 max sulfate   | 2009-12-09      2.08       2.1 max nitrate
## 10 288 2002-09-11        NA      19.0 max sulfate   | 2009-12-09      2.08       2.1 max nitrate
## 11 289 2005-08-02        NA       5.7 max sulfate   |       <NA>        NA        NA        <NA>
## 12 290 2002-09-14        NA      24.8 max sulfate   | 2001-01-25      2.05       5.5 max nitrate
## 13 291 2002-08-30        NA      18.0 max sulfate   |       <NA>        NA        NA        <NA>
## 14 292 2005-06-21        NA      10.2 max sulfate   |       <NA>        NA        NA        <NA>
## 15 293 2005-04-16        NA       5.6 max sulfate   |       <NA>        NA        NA        <NA>
## 16 294 2005-06-27        NA      12.3 max sulfate   |       <NA>        NA        NA        <NA>
## 17 295 2000-10-21      0.69      12.4 max sulfate   | 2000-12-05      1.54       2.9 max nitrate
## 18 296 2002-08-30        NA      13.9 max sulfate   | 2001-02-12      2.62       5.3 max nitrate
## 19 297 2002-09-14        NA      19.2 max sulfate   | 2001-05-01      0.57       5.3 max nitrate
## 20 298 2002-12-10     15.10       8.7 max sulfate   | 2002-02-07     38.20       6.2 max nitrate
## 21 299 2004-01-22     16.40       4.7 max sulfate   | 2004-02-15     37.50       4.4 max nitrate
## 22 300 2001-01-04     18.70      14.6 max sulfate   | 2002-02-07     41.60       6.5 max nitrate