简体   繁体   English

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

[英]How do I stretch a list of floats in Python?

I'm working in Python and have a list of hourly values for a day. 我正在使用Python,并且列出了一天的每小时值。 For simplicity let's say there are only 10 hours in a day. 为简单起见,我们说一天只有10个小时。

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

I want to stretch this around the centre-point to 150% to end up with: 我想围绕中心点延伸到150%以达到:

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

Note this is just an example and I will also need to stretch things by amounts that leave fractional amounts in a given hour. 请注意,这只是一个示例,我还需要按照在给定小时内留下小数量的金额进行拉伸。 For example stretching to 125% would give: 例如,拉伸至125%将给出:

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

My first thought for handling the fractional amounts is to multiply the list up by a factor of 10 using np.repeat , apply some method for stretching out the values around the midpoint, then finally split the list into chunks of 10 and take the mean for each hour. 我对处理小数量的第一个想法是使用np.repeat将列表乘以因子10,应用一些方法来拉伸中点周围的值,然后最终将列表拆分为10的块并取平均值每小时。

My main issue is the "stretching" part but if the answer also solves the second part so much the better. 我的主要问题是“伸展”部分,但如果答案也能更好地解决第二部分问题。

I guess, you need something like that: 我想,你需要这样的东西:

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

But be careful with odd count of hours. 但要小心奇数小时。

If I look at the expected output, the algorithm goes something like this: 如果我查看预期的输出,算法是这样的:

  • start with a list of numbers, values >0.0 indicate working hours 从数字列表开始,值> 0.0表示工作时间
  • sum those hours 总结那些时间
  • compute how many extra hours are requested 计算请求多少小时
  • divide those extra hours over both ends of the sequence by prepending or appending half of this at each 'end' 通过在每个'末端'前加或减半,将这些额外的小时数除以序列的两端

So: 所以:

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

Gives as output: 作为输出:

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]

This is what I've ended up doing. 这就是我最终做的事情。 It's a little ugly as it needs to handle stretch coefficients less than 100%. 它有点难看,因为它需要处理小于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: http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python#answer-312464

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM