我有一份清单清单,我想要" ngram"它们,意思是每行我要追加N-1(其中N是作为参数传递的数字)跟随行,即:。
1 2 3
4 5 6
7 8 9
1 2 3
n = 2会给我一个只有3行(行 - n + 1)的矩阵:
1 2 3 4 5 6 // row1+row2
4 5 6 7 8 9 // row2+row3
7 8 9 1 2 3 // row3+row4
对于n = 3:
1 2 3 4 5 6 7 8 9 // row1+row2+row3
4 5 6 7 8 9 1 2 3 // row2+row3+row4
对于n = 4,它将返回1行,所有行连接在一起,对于n> 4,它将失败。
我在R中有一个相当简单的代码(R newbie here):
ngram <- function(inp, window){
rows <- dim(inp)[1]
cols <- dim(inp)[2]
resRows <- rows - window + 1
res <- c()
for(idx in 1:resRows) {
newRow <- inp[idx,]
for(ii in 1:(window-1)) {
newRow <- c(newRow, inp[idx+ii,])
}
res <- rbind(res,newRow)
}
return(res)
}
iot <- read.csv("resources/data.csv")
iot <- ngram(iot, 5)
我认为,问题在于c(newRow, inp[idx+ii,])
,如果我举例n=10
,这个问题非常缓慢。有没有更好的方法来做我想做的事情?
答案 0 :(得分:4)
我们假设你有一个以下矩阵
a <- matrix(1:12, 4, 3, byrow = T)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
[4,] 10 11 12
您可以使用cbind
(n = 2,如您的示例)
cbind(a[1:(nrow(a) - 1),], a[2:nrow(a),])
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 4 5 6 7 8 9
[3,] 7 8 9 10 11 12
如果我理解你的ngram函数,它应该以这种方式重写
ngram <- function(inp, window){
N <- nrow(inp)
cbind(inp[1:(N - window + 1),], inp[window:N,])
}
答案 1 :(得分:2)
另一种方法是使用matrix
从各个元素构建一个新矩阵。
matSplat <- function(myMat, n) {
# get a list of the rows to combine
rows <- lapply(seq_len(nrow(myMat)-(n-1)), function(i) i:(i+n-1))
# transpose the matrix
myMat.t <- t(myMat)
# build up the new matrix
matrix(unlist(lapply(rows, function(i) myMat.t[,i])), nrow(myMat)-(n-1), byrow=TRUE)
}
这导致
matSplat(myMat, 2)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 4 5 6 7 8 9
[3,] 7 8 9 1 2 3
matSplat(myMat, 3)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 2 3 4 5 6 7 8 9
[2,] 4 5 6 7 8 9 1 2 3
数据强>
myMat <- matrix(c(1:9, 1:3), ncol=3, byrow = TRUE)