我试图确定MATLAB或R是否具有类似于以下内容的功能。
说我有一个输入向量v
。
v = [1, 3, 1, 2, 4, 2, 1, 3]
我想生成一个等长w
的向量v
。w[i]
。每个元素v[i]
都应该告诉我以下内容:对于相应的值v
,到目前为止在v
中遇到此值的次数,即i
的所有元素职位w = [0, 0, 1, 0, 0, 1, 2, 1]
,但不包括职位{{1}}。在这个例子中
{{1}}
我真的想看看是否有任何统计或特定领域的语言都有这样的功能/指令以及它可能被称为什么。
答案 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.