找到一组!=0在lis中

2024-04-27 00:12:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一种在python列表中查找“plateaus”或组的简单方法。作为输入,我有如下内容:

mydata = [0.0, 0.0, 0.0, 0.0, 0.0, 0.143, 0.0, 0.22, 0.135, 0.44, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.33, 0.65, 0.22, 0.0, 0.0, 0.0, 0.0, 0.0]

我要提取每个“组”的中间位置。组在本例中定义为数据,即!=0,例如至少3个位置长。应忽略包含的单个零(如位置6)。在

基本上我想得到以下输出:

^{pr2}$

对于我的用例来说,获得非常精确的输出数据并不重要。[10,21]还是可以的。在

总结一下:第一组:[0.143, 0.0, 0.22, 0.135, 0.44, 0.1];第二组:[0.33, 0.65, 0.22]。现在是中间元素的位置(如果没有真正的中间值,则从中间向左或向右)。所以在输出中8是第一组的中间,而{}是第二组的中间。在

我已经试过一些方法了。但它们并不像我希望的那样稳定(例如:更多的零包围会导致问题)。所以在花更多时间在这个想法上之前,我想问一下是否有更好的方法来实现这个特性。我甚至认为这可能是一个普遍的问题。有没有可能已经有标准代码来解决这个问题?在

other questions描述了大致相同的问题,但我也需要在处理之前“平滑”数据。在

1.)平滑数据-去除被包围的零

^{3}$

2.)在平滑列表中查找起始点(如果值为!=0,前面的值是0,它应该是一个起始点)。如果找到了端点:使用找到的最后一个startpoint和当前端点获取组的中间位置并将其写入deque。在

laststart = 0
lastend = 0
myoutput = deque()

for i in range(1, len(y_smooth)-1):
        #detect start:
        if y_smooth[i]!=0 and y_smooth[i-1]==0:
            laststart = i   
        #detect end:
        elif y_smooth[i]!=0 and y_smooth[i+1]==0 and laststart+2 < i:
            lastend = i
            myoutput.appendleft(laststart+(lastend-laststart)/2)

编辑:为了简化一切,我在开始时只给出了一个输入数据的简短示例。这个短列表实际上会导致一个有问题的平滑输出-整个列表将被平滑并且不会留下零。actual input dataactual input data after smoothing


Tags: and数据方法列表inputdata端点smooth
3条回答

如您所述,查找组的一个相当简单的方法是将数据转换为布尔数组,其中一个用于组内的数据,0表示组外的数据,然后计算两个连续值的差,这样一来,组的开始为1,结束时为-1。在

下面是一个例子:

import numpy as np

mydata = [0.0, 0.0, 0.0, 0.0, 0.0, 0.143, 0.0, 0.22, 0.135, 0.44, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.33, 0.65, 0.22, 0.0, 0.0, 0.0, 0.0, 0.0]
arr = np.array(mydata)

mask = (arr!=0).astype(np.int) #array that contains 1 for every non zero value, zero other wise
padded_mask =  np.pad(mask,(1,),"constant") #add a zero at the start and at the end to handle edge cases
edge_mask = padded_mask[1:] - padded_mask[:-1] #diff between a value and the following one 
#if there's a 1 in edge mask it's a group start
#if there's a -1 it's a group stop

#where gives us the index of those starts and stops
starts = np.where(edge_mask == 1)[0]
stops = np.where(edge_mask == -1)[0]
print(starts,stops)

#we format groups and drop groups that are too small
groups = [group for group in zip(starts,stops) if (group[0]+2 < group[1])]


for group in groups:
        print("start,stop : {}  middle : {}".format(group,(group[0]+group[1])/2) ) 

以及输出:

^{pr2}$

第2部分-找到组中点:

mydata = [0.0, 0.0, 0.0, 0.0, 0.0, 0.143, 0.0, 0.22, 0.135, 0.44, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
          0.0, 0.0, 0.33, 0.65, 0.22, 0.0, 0.0, 0.0, 0.0, 0.0]

groups = []
last_start = 0
last_end = 0
in_group = 0

for i in range(1, len(mydata) - 1):
    if not in_group:
        if mydata[i] and not mydata[i - 1]:
            last_start = i
            in_group = 1
    else:  # a group continued.
        if mydata[i]:
            last_end = i
        elif last_end - last_start > 1:  # we have a group i.e. not single non-zero value
            mid_point = (last_end - last_start) + last_start
            groups.append(((last_end - last_start)//2) + last_start)
            last_start, last_end, in_group = (0, 0, 0)
        else:  # it was just a single non-zero.
            last_start, last_end, in_group = (0, 0, 0)

print(groups)

输出:

^{pr2}$

平滑后的数据不剩零:

import numpy as np

def smooth(y, box_pts):
    box = np.ones(box_pts)/box_pts
    print(box)
    y_smooth = np.convolve(y, box, mode='same')
    return y_smooth

mydata = [0.0, 0.0, 0.0, 0.0,-0.2, 0.143, 
          0.0, 0.22, 0.135, 0.44, 0.1, 0.0, 
          0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 
          0.33, 0.65, 0.22, 0.0, 0.0, 0.0, 
          0.0, 0.0]

y_smooth = smooth(mydata, 27)
print(y_smooth)

输出:

^{pr2}$

在原始数据中找到它的方法是:

def findGroups(data, minGrpSize=1):
  startpos = -1
  endpos = -1
  pospos = []
  for idx,v in enumerate(mydata):
    if v > 0 and startpos == -1:
      startpos = idx
    elif v == 0.0:
      if startpos > -1:
       if idx < (len(mydata)-1) and mydata[idx+1] != 0.0:
         pass # ignore one 0.0 in a run
       else:
         endpos = idx

      if startpos > -1:
        if endpos >-1 or idx == len(mydata)-1: # both set or last one 
          if (endpos - startpos) >= minGrpSize:
              pospos.append((startpos,endpos))
          startpos = -1
          endpos = -1
  return pospos

pos = findGroups(mydata,1)
print(*map(lambda x: sum(x) // len(x), pos))

pos = findGroups(mydata,3)
print(*map(lambda x: sum(x) // len(x), pos))

pos = findGroups(mydata,5)
print(*map(lambda x: sum(x) // len(x), pos))

输出:

8 20
8 20
8 

相关问题 更多 >