R 使用apply函数根据条件简化替换向量元素
我有一个数据集,它有一个名为R 使用apply函数根据条件简化替换向量元素,r,R,我有一个数据集,它有一个名为Region的变量,代表澳大利亚的不同地区。以下是数据中的25行: > head(sample.2013$Region, n = 25) [1] QLD major urban - capital city VIC rural NSW regional - low urbanisation [4] SA regional - low urbanisation NSW regional - low urb
Region
的变量,代表澳大利亚的不同地区。以下是数据中的25行:
> head(sample.2013$Region, n = 25)
[1] QLD major urban - capital city VIC rural NSW regional - low urbanisation
[4] SA regional - low urbanisation NSW regional - low urbanisation Tas rural
[7] ACT major urban - capital city QLD rural ACT major urban - capital city
[10] NT regional - low urbanisation NSW other QLD rural
[13] ACT major urban - capital city VIC regional - high urbanisation Tas rural
[16] QLD major urban - capital city Tas rural VIC regional - high urbanisation
[19] QLD rural Tas rural VIC rural
[22] QLD other urban Tas rural VIC rural
[25] ACT major urban - capital city
36 Levels: ACT major urban - capital city NSW major urban - capital city NSW other urban ... ?
原始解决方案
我需要根据此列中的变量创建另一个名为state
的变量。目前,我正在使用蛮力方法创建一个新向量,如下所示:
add_states <- function(sample.2013) {
# Add states from the region variable
sample.2013$State[grepl('NSW', sample.2013$Region) == TRUE] <- 'NSW'
sample.2013$State[grepl('VIC', sample.2013$Region) == TRUE] <- 'VIC'
sample.2013$State[grepl('QLD', sample.2013$Region) == TRUE] <- 'QLD'
sample.2013$State[grepl('WA', sample.2013$Region) == TRUE] <- 'WA'
sample.2013$State[grepl('SA', sample.2013$Region) == TRUE] <- 'SA'
sample.2013$State[grepl('Tas', sample.2013$Region) == TRUE] <- 'TAS'
sample.2013$State[grepl('TAS', sample.2013$Region) == TRUE] <- 'TAS'
sample.2013$State[grepl('ACT', sample.2013$Region) == TRUE] <- 'ACT'
sample.2013$State[grepl('NT', sample.2013$Region) == TRUE] <- 'NT'
return(sample.2013)
}
add_state <- function(input, output, state) {
# Change the variable y in place, prevents duplication
output <- replace(output, grepl(state, input, ignore.case = TRUE), state)
output
}
state_codes <- c('NSW', 'VIC', 'QLD', 'WA', 'SA', 'TAS', 'ACT', 'NT')
test_vector <- head(sample.2013$Region, n = 500)
y = vector('character', length = length(test_vector))
for (i in 1:length(state_codes)) {
y <- add_state(test_vector, y, state_codes[i])
}
table(y)
y
ACT NSW NT QLD SA TAS VIC WA
14 99 50 42 49 98 92 45 11
但这也相当冗长,for循环不是惯用的R。我无法用apply函数替换这段代码,并让它替换向量中的值,而不是创建一堆其他向量
拉普拉
这是我用lappy
管理过的最好的一次:
add_state3 <- function(x, state) {
x <- replace(x, grepl(state, x, ignore.case = TRUE), state)
x
}
test_vector_short <- c("NSW 1", "NSW 2", "Vic", "Goo")
> output <- lapply(state_codes, add_state3, x = test_vector_short)
> output
[[1]]
[1] "NSW" "NSW" "Vic" "Goo"
[[2]]
[1] "NSW 1" "NSW 2" "VIC" "Goo"
[[3]]
[1] "NSW 1" "NSW 2" "Vic" "Goo"
[[4]]
[1] "NSW 1" "NSW 2" "Vic" "Goo"
[[5]]
[1] "NSW 1" "NSW 2" "Vic" "Goo"
[[6]]
[1] "NSW 1" "NSW 2" "Vic" "Goo"
[[7]]
[1] "NSW 1" "NSW 2" "Vic" "Goo"
[[8]]
[1] "NSW 1" "NSW 2" "Vic" "Goo"
add_state3您可以使用gsub
组合您的搜索和替换,例如gsub('^.*\\bNT\\b.*','NT')
将替换所有匹配的NT字符串(\\b
以避免类似“pint”匹配“NT”的事情)
如果将正则表达式设置为类似于'^.*\\b(NSW | NT | QLD |…)\b.*
,然后替换为\\1
(捕获的匹配项),则可以执行以下操作:
state.regex <- sprintf('^.*\\b(%s)\\b.*$', paste(state_codes, collapse='|'))
# "^.*\\b(NSW|VIC|QLD|WA|SA|TAS|ACT|NT)\\b.*$"
gsub(state.regex, '\\1', test_vector_short, ignore.case=T)
# [1] "NSW" "NSW" "Vic" "Goo"
state.regex似乎有一种模式是STATECODE-other-stuff
,因此您可以strsplit
并获取第一个元素
使用测试:
test <- c(
"QLD major urban - capital city",
"Vic rural",
"NSW regional - low urbanisation",
"SA regional - low urbanisation",
"NSW regional - low urbanisation",
"guff and goo"
)
result <- toupper(sapply(strsplit(test," "),`[`,1))
replace(result, !result %in% state_codes, NA)
#[1] "QLD" "VIC" "NSW" "SA" "NSW" NA
test由于每个区域的第一个单词是状态代码,您可以去掉其余的单词,并将结果用作新的state
变量:
sample.2013 <- data.frame(Region=c('QLD major urban - capital city','VIC rural','NSW regional - low urbanisation','SA regional - low urbanisation','NSW regional - low urbanisation Tas rural','ACT major urban - capital city','QLD rural','ACT major urban - capital city','NT regional - low urbanisation','NSW other','QLD rural','ACT major urban - capital city','VIC regional - high urbanisation Tas rural','QLD major urban - capital city','Tas rural','VIC regional - high urbanisation','QLD rural','Tas rural','VIC rural','QLD other urban','Tas rural','VIC rural','ACT major urban - capital city'));
sample.2013$state <- toupper(sub(' .*','',sample.2013$Region));
sample.2013;
## Region state
## 1 QLD major urban - capital city QLD
## 2 VIC rural VIC
## 3 NSW regional - low urbanisation NSW
## 4 SA regional - low urbanisation SA
## 5 NSW regional - low urbanisation Tas rural NSW
## 6 ACT major urban - capital city ACT
## 7 QLD rural QLD
## 8 ACT major urban - capital city ACT
## 9 NT regional - low urbanisation NT
## 10 NSW other NSW
## 11 QLD rural QLD
## 12 ACT major urban - capital city ACT
## 13 VIC regional - high urbanisation Tas rural VIC
## 14 QLD major urban - capital city QLD
## 15 Tas rural TAS
## 16 VIC regional - high urbanisation VIC
## 17 QLD rural QLD
## 18 Tas rural TAS
## 19 VIC rural VIC
## 20 QLD other urban QLD
## 21 Tas rural TAS
## 22 VIC rural VIC
## 23 ACT major urban - capital city ACT
sample.2013次要要点:你不需要grepl(…)==TRUE
中的==TRUE,因为grepl()
已经返回了一个逻辑向量(正如测试本身所示)。@bgoldst是的,我在发布之后注意到了这一点。干杯