如何使用 TraMineR 将噪声引入序列数据?
How to introduce noise into sequence data using TraMineR?
出于模拟目的,我想随机更改序列数据集中的状态。目标是了解聚类质量的不同度量如何随着数据中不同程度的结构而变化。
如果我要引入缺失,TraMineRextras 中有方便的 seqgen.missing()
函数,但它只会添加缺失状态。我将如何随机选择一个比例 p
的序列,并随机插入一个随机选择的字母表元素,插入概率为 p_g
、p_l
和 p_r
他们在中间、左边和右边?
下面是一个 seq.rand.chg
函数(改编自 seqgen.missing
),它将状态变化随机应用于一定比例的 p.cases
序列。对于每个随机选择的序列,函数随机改变状态
当p.gaps > 0
时,位置的比例在0
和p.gaps
之间;
当p.left > 0
and/orp.right > 0
时,最多p.left
(p.right
)个比例左(右)位置。
与seqgen.missing
函数一样,p.gaps
、p.left
和p.right
是每个选定序列中发生变化的最大比例。这些不完全是您的概率 p_g
、p_l
和 p_r
。但是为此调整功能应该很容易。
函数如下:
seq.rand.chg <- function(seqdata, p.cases=.1, p.left=.0, p.gaps=0.1, p.right=.0){
n <- nrow(seqdata)
alph <- alphabet(seqdata)
lalph <- length(alph)
lgth <- max(seqlength(seqdata))
nm <- round(p.cases * n, 0)
## selecting cases
idm <- sort(sample(1:n, nm))
rdu.r <- runif(n,min=0,max=p.right)
rdu.g <- runif(n,min=0,max=p.gaps)
rdu.l <- runif(n,min=0,max=p.left)
for (i in idm){
# inner positions
gaps <- sample(1:lgth, round(rdu.g[i] * lgth, 0))
seqdata[i,gaps] <- alph[sample(1:lalph, length(gaps), replace=TRUE)]
# left positions
nl <- round(rdu.l[i] * lgth, 0)
if (nl>0) seqdata[i,1:nl] <- alph[sample(1:lalph, nl, replace=TRUE)]
# right positions
nr <- round(rdu.r[i] * lgth, 0)
if (nr>0) seqdata[i,(lgth-nr+1):lgth] <- alph[sample(1:lalph, nr, replace=TRUE)]
}
return(seqdata)
}
我们用mvad
数据的前三个序列来说明函数的用法
library(TraMineR)
data(mvad)
mvad.lab <- c("employment", "further education", "higher education",
"joblessness", "school", "training")
mvad.shortlab <- c("EM", "FE", "HE", "JL", "SC", "TR")
mvad.seq <- seqdef(mvad[, 17:62], states = mvad.shortlab,
labels = mvad.lab, xtstep = 6)
mvad.ori <- mvad.seq[1:3,]
## Changing up to 50% of states in 30% of the sequences
seed=11
mvad.chg <- seq.rand.chg(mvad.ori, p.cases = .3, p.gaps=0.5)
## plotting the outcome
par(mfrow=c(3,1))
seqiplot(mvad.ori, with.legend=FALSE, main="Original sequences")
seqiplot(mvad.chg, with.legend=FALSE, main="After random changes")
seqlegend(mvad.ori, ncol=6 )
我们观察到更改已应用于随机选择的第三个序列。
出于模拟目的,我想随机更改序列数据集中的状态。目标是了解聚类质量的不同度量如何随着数据中不同程度的结构而变化。
如果我要引入缺失,TraMineRextras 中有方便的 seqgen.missing()
函数,但它只会添加缺失状态。我将如何随机选择一个比例 p
的序列,并随机插入一个随机选择的字母表元素,插入概率为 p_g
、p_l
和 p_r
他们在中间、左边和右边?
下面是一个 seq.rand.chg
函数(改编自 seqgen.missing
),它将状态变化随机应用于一定比例的 p.cases
序列。对于每个随机选择的序列,函数随机改变状态
当
p.gaps > 0
时,位置的比例在0
和p.gaps
之间;当
p.left > 0
and/orp.right > 0
时,最多p.left
(p.right
)个比例左(右)位置。
与seqgen.missing
函数一样,p.gaps
、p.left
和p.right
是每个选定序列中发生变化的最大比例。这些不完全是您的概率 p_g
、p_l
和 p_r
。但是为此调整功能应该很容易。
函数如下:
seq.rand.chg <- function(seqdata, p.cases=.1, p.left=.0, p.gaps=0.1, p.right=.0){
n <- nrow(seqdata)
alph <- alphabet(seqdata)
lalph <- length(alph)
lgth <- max(seqlength(seqdata))
nm <- round(p.cases * n, 0)
## selecting cases
idm <- sort(sample(1:n, nm))
rdu.r <- runif(n,min=0,max=p.right)
rdu.g <- runif(n,min=0,max=p.gaps)
rdu.l <- runif(n,min=0,max=p.left)
for (i in idm){
# inner positions
gaps <- sample(1:lgth, round(rdu.g[i] * lgth, 0))
seqdata[i,gaps] <- alph[sample(1:lalph, length(gaps), replace=TRUE)]
# left positions
nl <- round(rdu.l[i] * lgth, 0)
if (nl>0) seqdata[i,1:nl] <- alph[sample(1:lalph, nl, replace=TRUE)]
# right positions
nr <- round(rdu.r[i] * lgth, 0)
if (nr>0) seqdata[i,(lgth-nr+1):lgth] <- alph[sample(1:lalph, nr, replace=TRUE)]
}
return(seqdata)
}
我们用mvad
数据的前三个序列来说明函数的用法
library(TraMineR)
data(mvad)
mvad.lab <- c("employment", "further education", "higher education",
"joblessness", "school", "training")
mvad.shortlab <- c("EM", "FE", "HE", "JL", "SC", "TR")
mvad.seq <- seqdef(mvad[, 17:62], states = mvad.shortlab,
labels = mvad.lab, xtstep = 6)
mvad.ori <- mvad.seq[1:3,]
## Changing up to 50% of states in 30% of the sequences
seed=11
mvad.chg <- seq.rand.chg(mvad.ori, p.cases = .3, p.gaps=0.5)
## plotting the outcome
par(mfrow=c(3,1))
seqiplot(mvad.ori, with.legend=FALSE, main="Original sequences")
seqiplot(mvad.chg, with.legend=FALSE, main="After random changes")
seqlegend(mvad.ori, ncol=6 )
我们观察到更改已应用于随机选择的第三个序列。