我有一個數據表,有幾列用作我創建的手機驗證功能的輸入。從列輸入功能分配data.table列
library(data.table)
dt <- data.table(ID = c(1:6),
phone = c("0412 345 789","0438 123 456",
"041 2345 543", "(02) 1234 5678",
"9876 1234", "04123456789"),
state = c("NSW","QLD","SA"),
country = c("AU"),
phone_countries = c("AU","AU","AU","AU,US","AU,US","AU,US"))
# ID phone state country phone_countries
# 1: 1 0412 345 789 NSW AU AU
# 2: 2 0438 123 456 QLD AU AU
# 3: 3 041 2345 543 SA AU AU
# 4: 4 (02) 1234 5678 NSW AU AU,US
# 5: 5 9876 1234 QLD AU AU,US
# 6: 6 04123456789 SA AU AU,US
功能isValidPhone
看起來是這樣的(它被設計在幾個不同的位置,以驗證電話號碼。我省略了一些正則表達式的的爲了簡潔)。
isValidPhone <- function(phone, state, country, validation_countries) {
if (!(country %in% unlist(strsplit(validation_countries, ","))))
return(FALSE)
# remove whitespace, hyphens and brackets
phone_clean <- gsub("[[:space:]]|-|\\.|\\(|\\)", "", phone)
if (is.na(phone_clean) | phone_clean == '' | is.na(iconv(phone_clean, "", "ASCII")))
return(FALSE)
if (country == "AU") {
# append state area code if length is 8 digits
#print(paste("phone:", phone_clean, "state:", state))
if (nchar(phone_clean, "width") == 8)
if (state %in% c('ACT', 'NSW', 'QLD', 'VIC', 'TAS', 'SA', 'NT', 'WA'))
phone_clean <- switch (state,
'ACT' = paste0("02",phone_clean),
'NSW' = paste0("02",phone_clean),
'QLD' = paste0("07",phone_clean),
'VIC' = paste0("03",phone_clean),
'TAS' = paste0("03",phone_clean),
'SA' = paste0("08",phone_clean),
'NT' = paste0("08",phone_clean),
'WA' = paste0("08",phone_clean))
if (nchar(phone_clean, "width") == 9)
if(substr(phone_clean,1,1) %in% c(2:4,7,8))
phone_clean <- paste0("0", phone_clean)
return(grepl("^(?:\\+?61|0)[23478](?:[ -]?[0-9]){8}$",
as.character(phone_clean), ignore.case=TRUE))
}
}
我分配領域在我data.table
dt
稱爲validphone
dt[, validphone := isValidPhone(phone, state, country, phone_countries), by = 1:nrow(dt)]
# ID phone state country phone_countries validphone
# 1: 1 0412 345 789 NSW AU AU TRUE
# 2: 2 0438 123 456 QLD AU AU TRUE
# 3: 3 041 2345 543 SA AU AU TRUE
# 4: 4 (02) 1234 5678 NSW AU AU,US TRUE
# 5: 5 9876 1234 QLD AU AU,US TRUE
# 6: 6 04123456789 SA AU AU,US FALSE
不幸的是,我不得不使用by = 1:nrow(dt)
,就像我不這樣做,它將全列數據傳遞給導致問題的參數。這導致了我的真實數據集(〜300K)上的大量函數調用以及糟糕的性能。
我確實已經讀過,使用矢量化函數會更好,但是我不清楚該如何做到這一點。
有沒有更有效的方法來達到我想要的結果?
我不明白你爲什麼'unlist'和'in'的「驗證的國家」正在使用,如果這僅僅是在執行一行時間和第二國家專欄只有一個價值? –
該列是逗號分隔值的列表。 'phone_countries'有時看起來像「AU,US,UK」。我不相信功能的一部分會影響我的問題的對象。 – Dan
不知道'nchar(...,「width」)'是你想要的 – HubertL