【发布时间】:2015-07-15 01:25:48
【问题描述】:
我有一个数据集,其中包含一个名为 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)
}
这很好用,但是很难测试并且很脆弱。例如,我现在知道我可以将ignore-case 传递给grepl,这样就不需要两个塔斯马尼亚案例了。
For 循环
我已经能够用 for 循环和这样的函数替换上述“天真的”方法:
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 函数替换这段代码并让它替换向量中的值,而不是创建一堆其他向量。
应用
这是我使用 lapply 管理过的最好的:
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 函数,但它创建一个包含 8 个元素的列表,而不是替换元素。
问题
对冗长的序言感到抱歉,但本质上我的问题是如何使用应用函数根据某些标准就地更改向量的元素?
【问题讨论】:
-
次要观点:你不需要
grepl(...) == TRUE中的== TRUE,因为grepl()已经返回了一个逻辑向量(正如测试本身所表明的那样)。 -
@bgoldst 是的,我在发布后注意到了这一点。干杯。
标签: r