在Python中调整数据序列大小的最佳方法

在Python中调整数据序列大小的最佳方法,python,list,sequence,Python,List,Sequence,我有一个必须调整大小的数据序列(列表)。我已经为它写了一个函数,但它非常粗糙。有人知道解决这个问题的更好方法吗 预期行为: 在所有示例中,我的输入数据顺序如下: 编辑:即使示例是线性的,也不能期望序列是由公式构建的 [1,2,3,4,5,6,7,8,9,10] 当我将其从10个项目调整为5个项目时,我希望得到如下输出: [1,3,5,7,9]或[2,4,6,8,10] 现在,当您将数据序列的长度减半时,所有这些都不是很困难,但是我的输出序列的大小是可变的。我可以小于或大于原始序列的长度 当我将其

我有一个必须调整大小的数据序列(列表)。我已经为它写了一个函数,但它非常粗糙。有人知道解决这个问题的更好方法吗

预期行为: 在所有示例中,我的输入数据顺序如下: 编辑:即使示例是线性的,也不能期望序列是由公式构建的

[1,2,3,4,5,6,7,8,9,10]

当我将其从10个项目调整为5个项目时,我希望得到如下输出:

[1,3,5,7,9]
[2,4,6,8,10]

现在,当您将数据序列的长度减半时,所有这些都不是很困难,但是我的输出序列的大小是可变的。我可以小于或大于原始序列的长度

当我将其从10个项目调整为19个项目时(很容易手动操作),我希望如下所示:

[1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,7.5,8,8.5,9,9.5,10]

当前函数 其结果如下:

>>> sequenceResize(sequence, 5)
[1, 3, 5, 7, 9]
>>> sequenceResize(sequence, 19)
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10]
收缩是准确的,但扩展序列不是很好


是否有人知道正确解决此问题的现有方法或简单方法?

您可以使用np.lisnpace:

import numpy as np

list_in = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

resize = 19

list_out = np.linspace(list_in[0], list_in[-1], num=resize)

print(np.ndarray.tolist(list_out))
输出:

[1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0]

您应该计算两个列表中的索引之间的“步数”比率,而不是直接确定索引。请注意,与列表中的元素相比,步骤少了一步。然后,您可以获得
floor
ceil
项,并根据当前步骤的小数部分确定最终值,获得两者之间的加权平均值(参见下图)

或者使用
divmod
稍微短一点:

def sequenceResize(source, length):
    step = float(len(source) - 1) / (length - 1)
    for i in range(length):
        low, ratio = divmod(i * step, 1)
        high = low + 1 if ratio > 0 else low
        yield (1- ratio) * source[int(low)] + ratio * source[int(high)]
示例:

>>> sequence = [1, 2, 4, 8, 16]
>>> list(sequenceResize(sequence, 5))
[1, 2.0, 4.0, 8.0, 16.0]
>>> list(sequenceResize(sequence, 3))
[1, 4.0, 16.0]
>>> list(sequenceResize(sequence, 10))
[1, 1.44444, 1.88889, 2.66667, 3.55556, 4.88889, 6.66667, 8.88889, 12.44444, 16.0]
>>> list(sequenceResize(sequence, 19))
[1, 1.22222, 1.44444, 1.66667, 1.88889, 2.22222, 2.66667, 3.11111, 3.55556, 4.0, 4.88889, 5.77778, 6.66667, 7.55556, 8.88889, 10.66667, 12.44444, 14.22222, 16.0]
另一个例子作为说明。蓝色是原始值,红色是插值值


我理解扩展部分:您只需要一个包含x个元素的列表,从1到10,因此步骤是可变的。我没有得到的是当缩小列表时您所期望的,您可以使用最小和最大元素,并从该范围随机生成剩余的数字。使用random.uniform(min,max)生成浮点数。随着收缩,我希望从
[1,2,3,4,5,6,7,8,9]
到例如
[1,4,6,9]
这些数字的间隔是否均匀?如果“调整大小”
[1,2,4,8,16]
,您需要进行插值。如果你想保持数据的离散性,也许可以使用最近邻缩放。你能用输出的内容更新你的答案吗?听起来不错,但如果序列不是一个单一的公式,线性或其他形式,它也有效吗?@Lakitna否,只在列表中的第一个和最后一个值之间插值。这对我来说非常有效!谢谢你,托拜厄斯:)我唯一添加的是
if key>len(source)-1:key=len(source)-1
,因为当长度=500时,最后一个键可能是
499.00000001
@Lakitna,正是因为这个原因,我在早期版本中有类似
key=round(I*step,5)
(参见编辑历史记录),但在后来的测试中,这似乎不再必要了。但是你的也应该可以,当你试图把一个序列扩展很多的时候就会发生这种情况。可能有些python会在每次迭代中进行堆栈。您的舍入解决方案比我的解决方案优雅得多,因此我将交换它。
def sequenceResize(source, length):
    step = float(len(source) - 1) / (length - 1)
    for i in range(length):
        low, ratio = divmod(i * step, 1)
        high = low + 1 if ratio > 0 else low
        yield (1- ratio) * source[int(low)] + ratio * source[int(high)]
>>> sequence = [1, 2, 4, 8, 16]
>>> list(sequenceResize(sequence, 5))
[1, 2.0, 4.0, 8.0, 16.0]
>>> list(sequenceResize(sequence, 3))
[1, 4.0, 16.0]
>>> list(sequenceResize(sequence, 10))
[1, 1.44444, 1.88889, 2.66667, 3.55556, 4.88889, 6.66667, 8.88889, 12.44444, 16.0]
>>> list(sequenceResize(sequence, 19))
[1, 1.22222, 1.44444, 1.66667, 1.88889, 2.22222, 2.66667, 3.11111, 3.55556, 4.0, 4.88889, 5.77778, 6.66667, 7.55556, 8.88889, 10.66667, 12.44444, 14.22222, 16.0]