2017-05-16 38 views
1

我有一個由0和非零數字組成的向量。我想知道每一個非零數字系列的長度和起始位置:找到一系列數字中的子系列的長度和位置

a = c(0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 2.6301334 1.8372030 0.0000000 0.0000000 0.0000000 1.5632647 1.1433757 0.0000000 1.5412216 0.8762267 0.0000000 1.3087967 0.0000000 0.0000000 0.0000000) 

基於以前的文章中,很容易找到非零區域的起始位置: Finding the index of first changes in the elements of a vector in R

c(1,1+which(diff(a)!=0)) 

但是我似乎無法配置發現這些區域的長度的方式....

我曾嘗試以下:

dif=diff(which(a==0)) 
dif_corrected=dif-1 # to correct for the added lengths 
row=rbind(postion=seq(length(a)), length=c(1, dif_corrected)) 

position 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
length  1 0 0 0 0 2 0 0 2  2  1  0  0  1  0 

注:未顯示所有的列(實際上有20)

然後我子集這個帶走0值:

> row[,-which(row[2,]==0)] 
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] 
position 1 6 9 10 11 14 19 
length  1 2 2 2 1 1 2 

這似乎是想出了一個體面的方式序列中每個非零系列的位置和長度,但它是不正確的:

位置9(標識爲非零系列的起點)是0而非10和11是非零我期望位置10和長度2出現在這裏.... 唯一正確的結果是位置6,它是第一個非零系列的開始位置 - 它被正確識別爲具有長度爲2-的所有其他位置不正確。

任何人都可以告訴我如何正確索引來確定每個非零系列的起始位置和相應的長度嗎?

注意我只是R中這樣做是因爲其指揮的實用性,但它也將是很好的知道如何做到這一點numpy的和創造職位的字典和長度值

+0

你h在你的例子中有許多不一致之處。什麼是'v'?當你將'a'定義爲矢量時,爲什麼你有'a [1,]'?什麼是正確的結果。請修改 – Sotos

+0

道歉將正確 –

回答

1

好像rle可能在這裏很有用。

# a slightly simpler vector 
a <- c(0, 0, 1, 2, 0, 2, 1, 2, 0, 0, 0, 1) 

# runs of zero and non-zero elements 
r <- rle(a != 0) 

# lengths of non-zero elements 
r$lengths[r$values] 
# [1] 2 3 1 

# start of non-zero runs 
cumsum(r$lengths)[r$values] - r$lengths[r$values] + 1 
# [1] 3 6 12 

這也適用於矢量僅0或非0,並且不依賴於向量是否啓動/同0或非0結束。例如: -

a <- c(1, 1) 
a <- c(0, 0) 
a <- c(1, 1, 0, 1, 1) 
a <- c(0, 0, 1, 1, 0, 0) 

一個可能data.table替代,使用rleid創建組,並.I得到啓動指數和計算長度。

library(data.table) 
d <- data.table(a) 
d[ , .(start = min(.I), len = max(.I) - min(.I) + 1, nonzero = (a != 0)[1]), 
    by = .(run = rleid(a != 0))] 
#  run start len nonzero 
# 1:  1  1 2 FALSE 
# 2:  2  3 2 TRUE 
# 3:  3  5 1 FALSE 
# 4:  4  6 3 TRUE 
# 5:  5  9 3 FALSE 
# 6:  6 12 1 TRUE 

如果需要,運行可以很容易地被'非零'列切割。

0

定義

sublistLen = function(list) { 
    z_list <- c(0, list, 0) 
    ids_start <- which(diff(z_list != 0) == 1) 
    ids_end <- which(diff(z_list != 0) == - 1) 
    lengths <- ids_end - ids_start 

    return(
     list(
     'ids_start' = ids_start, 
     'ids_end' = ids_end - 1, 
     'lengths' = lengths) 
     ) 
} 

> a <- c(-2,0,0,12,5,0,124,0,0,0,0,4,48,24,12,2,0,9,1) 
> sublistLen(a) 
$ids_start 
[1] 1 4 7 12 18 

$ids_end 
[1] 1 5 7 16 19 

$lengths 
[1] 1 2 1 5 2 
1

對於numpy這是一個平行方法@Maple(與具有非零結束陣列修復):

def subSeries(a): 
    d = np.logical_not(np.isclose(a, np.zeros_like(a))).astype(int) 
    starts = np.where(np.diff(np.r_[0, d, 0]) == 1)) 
    ends = np.where(np.diff(np.r_[0, d, 0]) == -1)) 
    return np.c_[starts - 1, ends - starts]