2

我有一个代表观察时间的浮点值列表。(每个浮点值实际上都可以表示为一个整数,但我希望针对未来可能的情况进行概括)。

list_hrs = [4,6,8,8,10] # actual list is thousands of floats

我试图用零填充与其索引不匹配的值,同时只计算一次出现的重复条目。根据示例列表,我想要

list_hrs = [0,0,0,0,4,0,6,0,8,8,0,10]

前四个条目是0因为从0到包含四个数字30之间的4and6是因为5缺少而在那里被通缉;与0之间类似。那里需要介于和之间,因为缺少该值。此外,重复的 's 保持不变,因为稍后将在我的代码中处理它们;在 padding 之前应该只计算一次出现的 duplicate 。6808109880

我的第一次尝试是尝试这个:

for index in range(len(list_hrs)):
    if list_hrs != index:
        list_hrs.insert(index, 0)

>> [0, 0, 0, 0, 0, 4, 6, 8, 8, 10]

然后,我阅读了不同的 SO 帖子,并得出这样的印象,即最好先制作一个0's 列表,其长度应等于所考虑的数据点的数量。然后,非零条目可以替换0条目。所以,我尝试了以下方法:

def make_zeros(hrs=list_hrs): # make list of 0's
    num_zer = int(max(hrs))
    list_zer = [0 for index in range(num_zer+1)]
    return list_zer

但是我不确定在此之后如何实施条件以达到预期的结果。我在想有一种方法可以enumerate用来检查索引是否与该索引处的值匹配,但由于条目重复(8例如上面示例中的 's ),我不确定如何继续。

这种方法是继续前进的好方向,还是有更有效/更简单的方法来达到预期的结果?任何帮助或建议将不胜感激。

4

2 回答 2

2

这是一种矢量化方法 -

def make_zeros_vectorized(A, dtype=float):
    a = np.asarray(A).astype(int)
    idx = a + np.r_[0, (a[1:] == a[:-1]).cumsum()]
    out = np.zeros(idx[-1]+1,dtype=dtype)
    out[idx] = A
    return out

样品运行 -

In [95]: A
Out[95]: [4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0]

In [96]: make_zeros_vectorized(A)
Out[96]: 
array([  0.,   0.,   0.,   0.,   4.,   0.,   6.,   0.,   8.,   8.,   0.,
        10.,  10.,  10.,   0.,   0.,   0.,  14.,   0.,  16.])

In [100]: A
Out[100]: [4.0, 4.0, 4.0, 4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0]

In [101]: make_zeros_vectorized(A)
Out[101]: 
array([  0.,   0.,   0.,   0.,   4.,   4.,   4.,   4.,   0.,   6.,   0.,
         8.,   8.,   0.,  10.,  10.,  10.,   0.,   0.,   0.,  14.,   0.,
        16.])

涉及的步骤

输入列表

In [71]: A = [4.0,6.0,8.0,8.0,10.0,10.0,10.0,14.0,16.0]

转换为数组

In [72]: a = np.asarray(A).astype(int)

In [73]: a
Out[73]: array([ 4,  6,  8,  8, 10, 10, 10, 14, 16])

创建一个重复的蒙版。这是这种方法的核心,因为我们计划稍后使用累积求和。将重复项表示为 True,当累积求和时将产生增量值,用作将输入数组值放入输出数组的增量索引

In [74]: a[1:] == a[:-1]
Out[74]: array([False, False,  True, False,  True,  True, False, False], dtype=bool)

In [75]: (a[1:] == a[:-1]).cumsum()
Out[75]: array([0, 0, 1, 1, 2, 3, 3, 3])

在开头附加一个零,因为早期的 "a[1:] == a[:-1]" 会导致一个元素更少的数组

In [76]: np.r_[0, (a[1:] == a[:-1]).cumsum()]
Out[76]: array([0, 0, 0, 1, 1, 2, 3, 3, 3])

最后,添加到输入数组,以便重复移动/添加一个,从而为我们提供要分配输出数组的索引

In [77]: a + np.r_[0, (a[1:] == a[:-1]).cumsum()]
Out[77]: array([ 4,  6,  8,  9, 11, 12, 13, 17, 19])

后面的步骤基本上是创建一个输出数组并a使用之前获得的索引将值分配给它。


如果您需要零掩码或那些索引,这里有一个修改版本 -

def get_zeros_mask(A):
    a = np.asarray(A).astype(int)
    idx = a + np.r_[0, (a[1:] == a[:-1]).cumsum()]
    mask = np.ones(idx[-1]+1,dtype=bool)
    mask[idx] = 0
    return mask

样品运行 -

In [93]: A
Out[93]: [4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0]

In [94]: make_zeros_vectorized(A)
Out[94]: 
array([  0.,   0.,   0.,   0.,   4.,   0.,   6.,   0.,   8.,   8.,   0.,
        10.,  10.,  10.,   0.,   0.,   0.,  14.,   0.,  16.])

In [95]: get_zeros_mask(A)
Out[95]: 
array([ True,  True,  True,  True, False,  True, False,  True, False,
       False,  True, False, False, False,  True,  True,  True, False,
        True, False], dtype=bool)

In [96]: np.flatnonzero(get_zeros_mask(A))
Out[96]: array([ 0,  1,  2,  3,  5,  7, 10, 14, 15, 16, 18])
于 2017-05-01T09:11:56.173 回答
1

再举一个例子:

list_hrs = [4,6,8,8,10]
lh = iter(list_hrs)
fit = range(int(max(list_hrs))+1)

result = [0 if i not in list_hrs else next(lh) for i in fit for _ in range(list_hrs.count(i)) or [1]]
于 2017-05-01T09:17:28.833 回答