用于计算已经看到值的次数的函数/指令

时间:2014-08-20 09:19:11

标签: r matlab programming-languages dsl instructions

我试图确定MATLAB或R是否具有类似于以下内容的功能。

说我有一个输入向量v

v = [1, 3, 1, 2, 4, 2, 1, 3]

我想生成一个等长w的向量vw[i]。每个元素v[i]都应该告诉我以下内容:对于相应的值v,到目前为止在v中遇到此值的次数,即i的所有元素职位w = [0, 0, 1, 0, 0, 1, 2, 1] ,但不包括职位{{1}}。在这个例子中

{{1}}

我真的想看看是否有任何统计或特定领域的语言都有这样的功能/指令以及它可能被称为什么。

4 个答案:

答案 0 :(得分:7)

在Matlab中没有这方面的功能(据我所知),但你可以这样做:

w = sum(triu(bsxfun(@eq, v, v.'), 1));

说明:bsxfun(...)将每个元素相互比较。然后triu(..., 1)仅保留元素与之前元素的匹配(即对角线以上的值)。最后sum(...)添加了与之前元素的所有巧合。


更明确但更慢的替代方案(不推荐)是:

w = arrayfun(@(n) sum(v(1:n-1)==v(n)), 1:numel(v));

说明:对于每个索引n(其中n变为1:numel(v)),将所有先前元素v(1:n-1)与当前元素v(n)进行比较,然后获取匹配数(sum(...))。

答案 1 :(得分:7)

R中,您可以尝试:

 v <- c(1,3,1,2,4,2,1,3)
 ave(v, v, FUN=seq_along)-1
 #[1] 0 0 1 0 0 1 2 1

解释

 ave(seq_along(v), v, FUN=seq_along)  #It may be better to use `seq_along(v)` considering different classes i.e. `factor` also.
 #[1] 1 1 2 1 1 2 3 2

在这里,我们按v对元素序列进行分组。对于匹配同一组的元素,seq_along函数将创建1,2,3 etc。在v的情况下,同一组1的元素位于1,3,7位置,因此相应的位置将为1,2,3。通过使用1减去,我们将能够从0开始。

要更好地理解它,

 lst1 <- split(v,v)
 lst2 <- lapply(lst1, seq_along)
 unsplit(lst2, v)
 #[1] 1 1 2 1 1 2 3 2

使用data.table

  library(data.table)
  DT <- data.table(v, ind=seq_along(v))
  DT[, n:=(1:.N)-1, by=v][,n[ind]]
  #[1] 0 0 1 0 0 1 2 1

答案 2 :(得分:4)

R有一个名为make.unique的函数,可用于获取所需的结果。首先使用它来使所有元素都是唯一的:

(v.u <- make.unique(as.character(v))) # it only works on character vectors so you must convert first
[1] "1"   "3"   "1.1" "2"   "4"   "2.1" "1.2" "3.1"

然后您可以使用此向量,删除原始数据,将空白转换为0,然后转换回整数以获取计数:

as.integer(sub("^$","0",sub("[0-9]+\\.?","",v.u)))
[1] 0 0 1 0 0 1 2 1

答案 3 :(得分:3)

如果你想在matlab中使用for循环,你可以得到结果:

res=v;
res(:)=0;
for c=1:length(v)
    helper=find(v==v(c));
    res(c)=find(helper==c);
end
与Luis Mendo的解决方案相比,

不确定运行时。现在就检查一下。

修改

运行代码10.000次会导致:

My Solution: Elapsed time is 0.303828 seconds 
Luis Mendo's Solution (bsxfun): Elapsed time is 0.180215 seconds.
Luis Mendo's Solution (arrayfun): Elapsed time is 3.868467 seconds.

因此bsxfun解决方案最快,然后是for循环,然后是arrayfun解决方案。现在要生成更长的v阵列,看看是否有变化。

编辑2 将v更改为

v = ceil(rand(100,1)*8);

导致更明显的运行时排名:

My Solution: Elapsed time is 4.020916 seconds.
Luis Mendo's Solution (bsxfun):Elapsed time is 0.808152 seconds.
Luis Mendo's Solution (arrayfun): Elapsed time is 22.126661 seconds.