如何在Python中拉伸一个浮点数列表?

4

我正在使用Python,并且有一天中每小时的值列表。为了简单起见,假设一天只有10个小时。

 [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]

我希望将此内容按中心点拉伸到150%,最终效果如下:

 [0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0]

请注意,这只是一个示例,我还需要按照一定的比例来拉伸内容,这样会在给定的小时内留下部分量。例如,将其拉伸至125%会得到以下结果:

 [0.0, 0.0, 0.5, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0, 0.0]

对于处理小数部分的想法是,使用np.repeat将列表乘以10的因子,应用一些方法来拉伸中点周围的值,最后将列表分成每小时的10个块,并取每小时的平均值。

我的主要问题是“拉伸”部分,但如果答案也解决了第二部分,那就更好了。


在初始状态下,数组是否总是只填充了1.0和0.0? - user4668606
你的列表是否总是看起来像这样:一堆零,一个数字,一堆零?元素的最大值是否为1.0?数字是否总是围绕中间对称? - sve
如果我想以中心为基准将[1, 1, 1]拉伸到50%,会得到什么? - sve
[1, 1, 1] 的值应该不变。我的目的是通过一个因子来表示延长工作时间,因此只有中间的值才有意义。 - Jamie Bull
1
你可以使用一些变通方法,但从问题的背景来看,像pandas这样的软件包可能是你最好的选择。你可以定义时间测量值,然后利用其功能填充和查询不同的范围。 - Joop
显示剩余8条评论
3个回答

1
我猜你需要这样的东西:

我猜,你需要像这样的东西:

def stretch(xs, coef):
  # compute new distibution
  oldDist = sum(hours[:len(hours)/2])
  newDist = oldDist * coef

  # generate new list
  def f(x):
    if newDist - x < 0:
      return 0.0
    return min(1.0, newDist - x)

  t = [f(x) for x in range(len(xs)/2)]
  res = list(reversed(t))
  res.extend(t)
  return res

但是要小心奇数小时。


1
如果我看一下期望的输出结果,该算法大致如下:
  • 从数字列表开始,值 >0.0表示工作时间
  • 对这些小时求和
  • 计算申请的额外工作小时数
  • 将这些额外的小时数分配到序列的两端,通过在每个“端点”前置或附加一半的小时数来实现
所以:
hours     = [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]
expansion = 130
extra_hrs = float(sum(hours)) * float(expansion - 100)/100

# find indices of the first and last non-zero hours
# because of floating point can't use "==" for comparison.
hr_idx    = [idx for (idx, value) in enumerate(hours) if value>0.001]

# replace the entries before the first and after the last 
# with half the extra hours
print "Before expansion:",hours
hours[ hr_idx[0]-1 ] = hours[ hr_idx[-1]+1 ] = extra_hrs/2.0
print "After  expansion:",hours

输出:

Before expansion: [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]
After  expansion: [0.0, 0.0, 0.6, 1.0, 1.0, 1.0, 1.0, 0.6, 0.0, 0.0]

0

这就是我最终做的。它有点丑陋,因为它需要处理小于100%的拉伸系数。

def stretch(xs, coef, centre):
    """Scale a list by a coefficient around a point in the list.

    Parameters
    ----------
    xs : list
        Input values.
    coef : float
        Coefficient to scale by.
    centre : int
        Position in the list to use as a centre point.

    Returns
    -------
    list

    """
    grain = 100    
    stretched_array = np.repeat(xs, grain * coef)

    if coef < 1:
        # pad start and end
        total_pad_len = grain * len(xs) - len(stretched_array)
        centre_pos = float(centre) / len(xs)
        start_pad_len = centre_pos * total_pad_len
        end_pad_len = (1 - centre_pos) * total_pad_len
        start_pad = [stretched_array[0]] * int(start_pad_len)
        end_pad = [stretched_array[-1]] * int(end_pad_len)
        stretched_array = np.array(start_pad + list(stretched_array) + end_pad)
    else:
        pivot_point = (len(xs) - centre) * grain * coef
        first = int(pivot_point - (len(xs) * grain)/2)
        last = first + len(xs) * grain
        stretched_array = stretched_array[first:last]

    return [round(chunk.mean(), 2) for chunk in chunks(stretched_array, grain)]


def chunks(iterable, n):
    """
    Yield successive n-sized chunks from iterable.
    Source: https://dev59.com/lnVC5IYBdhLWcg3wYQAp

    """
    for i in xrange(0, len(iterable), n):
        yield iterable[i:i + n]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接