7

我有一串数字不一定具有相同的长度,例如

0,0,1,2,1,0,0,0

1,1,0,1

2,1,2,0,1,0

我已将这些导入到 R 中的数据框中,例如上述三个字符串将给出以下三行(我将称之为df):

在此处输入图像描述

我正在寻找一些函数来帮助我理解数据。作为一个起点 - 给定一个数字向量x- 我想要一个“过程”P来建立包含x作为子向量的行数,例如 if x = c(2,1)then P(x) = 2、 if x = c(0,0,0)thenP(x) = 1和 if x = c(1,3)then P(x) = 0。我有更多类似的问题,但我希望我能够从这个问题中汲取逻辑并自己解决一些其他问题。

4

2 回答 2

6

编辑:正则表达式的方式是:

match.regex <- function(x,data){
  xs <- paste(x,collapse="_")
  dats <- apply(data,1,paste,collapse="_")
  sum(grepl(xs,dats))
}


> match.regex(c(1),dat)
[1] 3
> match.regex(c(0,0,0),dat)
[1] 1
> match.regex(c(1,2),dat)
[1] 2
> match.regex(5,dat)
[1] 0

令人惊讶的是,这个方法比这里给出的其他方法快,并且是我下面的解决方案的两倍,无论是在小型数据集还是大型数据集上。正则表达式显然得到了优化:

> benchmark(matching(c(1,2),dat),match.regex(c(1,2),dat),replications=1000)
                       test replications elapsed relative 
2 match.regex(c(1, 2), dat)         1000    0.15      1.0 
1    matching(c(1, 2), dat)         1000    0.36      2.4 

一种可以立即为您提供数字并更加矢量化的方法如下:

matching.row <- function(x,row){
    nx <- length(x)
    sid <- which(x[1]==row)
    any(sapply(sid,function(i) all(row[seq(i,i+nx-1)]==x)))
}

matching <- function(x,data)
  sum(apply(data,1,function(i) matching.row(x,i)),na.rm=TRUE)

在这里,您首先创建一个带有索引的矩阵,该索引将窗口移动到与您要匹配的向量长度相同的行上。然后对照向量检查这些窗口。每一行都遵循这种方法,返回 TRUE 的行的总和就是你想要的。

> matching(c(1),dat)
[1] 3
> matching(c(0,0,0),dat)
[1] 1
> matching(c(1,2),dat)
[1] 2
> matching(5,dat)
[1] 0
于 2012-12-19T12:54:56.910 回答
3

你需要apply一个函数来处理你的数据行:

apply(dat, MARGIN = 1, FUN = is.sub.array, x = c(2,1))

dat你的data.frame在哪里,并且is.sub.array是一个检查是否x包含在更大向量中的函数(实际上是你的data.frame的行)。

我不知道有任何可用的此类is.sub.array功能,所以我将如何编写它:

is.sub.array <- function(x, y) {
    j <- rep(TRUE, length(y))
    for (i in seq_along(x)) {
        if (i > 1) j <- c(FALSE, head(j, -1))
        j <- j & vapply(y, FUN = function(a,b) isTRUE(all.equal(a, b)),
                        FUN.VALUE = logical(1), b = x[i])
    }
    return(sum(j, na.rm = TRUE) > 0L)
}

( using 的优点all.equal是它可以用来比较numeric向量,这是正则表达式无法做到的。)

这里有一些例子:

apply(dat, 1, is.sub.array, x = c(1, 2))
# [1]  TRUE FALSE  TRUE
apply(dat, 1, is.sub.array, x = c(0, 0, 0))
# [1]  TRUE FALSE FALSE
apply(dat, 1, is.sub.array, x = as.numeric(c(NA, NA)))
# [1] FALSE  TRUE  TRUE

注意all.equal对您的数据类型很敏感,因此请小心使用x与您的数据类型相同(整数或数字)的 an。

于 2012-12-19T12:36:21.007 回答