【问题标题】:Comparing data in a list in python in a loop until no more pairs can be made在循环中比较python中列表中的数据,直到无法再进行配对
【发布时间】:2017-10-29 20:42:22
【问题描述】:

正如标题所示,我正在尝试循环遍历数据列表以创建对并继续这样做,直到无法再创建对为止。对于上下文,我正在使用浮点数,并且想要遍历列表中的所有元素,然后将它们与其他所有元素进行比较,以查看它们是否在当前项目上方或下方的 0.03 内。

如果它们是,那么我正在尝试在它们的列表中创建一个由高和低组成的元组。然后我想继续循环遍历整个列表,直到组合在一起的所有“范围”都被分组。

我尝试使用我所拥有的 Python 知识将一些代码组合在一起,并将其分解为可以单独查看但到目前为止还没有任何工作的更小的问题。离我最近的是下面不完整的代码:

s = []
t = ()
for item in items:
    for v in items:
      if v < (item + 0.03) and v > (item - 0.03):
         t = (item, v)
         s.append(t)

虽然我不确定在哪里插入循环,或者如何调节它,而且我还没有用元组替换匹配项,但这只是一个粗略的开始。

结果应该是这样的(我对细节不挑剔,只要我可以创建所有组):

初始列表: 1.05, 1.07, 1.18, 1.19, 1.22, 1.26, 1.30, 1.32

在第一次通过时,这会创建: [(1.07, 1.05), (1.19, 1.18), 1.22, 1.26, (1.30, 1.32)]

此时配对数字在元组中,其中第一个位置是范围的高位,第二个位置是范围的低位。

下一次传球(也是这个简短示例的最后一次传球)

[(1.07, 1.05), (1.22, 1.18), 1.22, 1.26, (1.30, 1.32)]

请注意,第二个元组的先前高点已被 0.031.22 范围内的新高点取代

这正是我想象的展开方式,但只要我达到找到所有对子范围的最终结果,那么我就会成功。

解释原因:我正在寻找图表上的“区域”(或者更确切地说是折线图的数据点)。我将相似点定义为彼此相距 0.03,完成后我将能够在图表上绘制水平线以显示活动区域。该区域不必有设定的高度,它可以大也可以小,只要每个点与最近的邻居的距离为 0.03 即可。此外,如果我们有 (1.01, 1.03) 和 (1.05, 1.08),列表将变为 (1.01, 1.08),所以我知道这个范围或组从 1.01 到 1.08。 (分别为低和高)。 1.03 和 1.05 不再重要,因为它们在该区域内。

【问题讨论】:

  • 结束列表应该是什么样的,你当前的代码会产生什么?
  • 为了更清楚,您是否可以添加一个值列表作为示例以及您希望从这些值中获取的元组列表。
  • 这个任务可以通过首先对数据进行排序来简化。
  • 谢谢,PatrickHaugh 和 Marco,我已经扩展了我认为应该如何解决的问题。
  • @PM2Ring,所以先从低到高对数据进行排序,还是沿着这些方向排序?我一点也不反对,但那会是什么样子呢?也许if current &lt; (next + 0.03) or current &gt; (next - 0.03)?根据我的低经验,我认为我仍然需要做同样的事情(比较,然后循环直到无法配对),对吧?

标签: python python-3.x


【解决方案1】:

我相信下面的代码可以满足您的需求。 ;)

我们首先遍历排序后的数据,测试当前项是否在前一项的限制范围内。如果是,我们将它添加到当前区域组中,否则它成为新组的开始。然后我们检查这些组,将它们浓缩为两个或一个项目的元组。

我们在执行测试时必须小心,因为可能会出现浮点错误。例如,1.22 - 1.19 的结果是 0.030000000000000027,它大于 0.03。为了解决这个问题,我将限制略微增加到 0.03001。有关此重要主题的更多详细信息,请参阅Is floating point math broken?

我的代码使用问题中给出的数据以及一些随机生成的数据测试make_zones

from random import seed, sample

seed(42)

# Adjust limit to handle floating-point errors
lim = 0.03001

def make_zones(data):
    # Collect values into groups
    groups = []
    t = data[:1]
    for u in data[1:]:
        if u - t[-1] <= lim:
            t.append(u)
        else:
            groups.append(t)
            t = [u]
    if t:
        groups.append(t)

    print('\n1st pass', groups)

    # Convert lists into 1 or 2 item tuples
    return [(u[-1], u[0]) if len(u)>1 else tuple(u) for u in groups]

# Tests

data = [1.05, 1.07, 1.18, 1.19, 1.22, 1.26, 1.30, 1.32]
print('Data', data)
print('Zones', make_zones(data), '\n')

# Make some random data
num = 20
data = [u / 100 for u in sample(range(100, 150), num)]
data.sort()
print('Data', data)
print('Zones', make_zones(data))

输出

Data [1.05, 1.07, 1.18, 1.19, 1.22, 1.26, 1.3, 1.32]

1st pass [[1.05, 1.07], [1.18, 1.19, 1.22], [1.26], [1.3, 1.32]]
Zones [(1.07, 1.05), (1.22, 1.18), (1.26,), (1.32, 1.3)] 

Data [1.01, 1.02, 1.05, 1.06, 1.07, 1.08, 1.13, 1.14, 1.15, 1.17, 1.27, 1.32, 1.34, 1.36, 1.37, 1.4, 1.44, 1.46, 1.47, 1.49]

1st pass [[1.01, 1.02, 1.05, 1.06, 1.07, 1.08], [1.13, 1.14, 1.15, 1.17], [1.27], [1.32, 1.34, 1.36, 1.37, 1.4], [1.44, 1.46, 1.47, 1.49]]
Zones [(1.08, 1.01), (1.17, 1.13), (1.27,), (1.4, 1.32), (1.49, 1.44)]

【讨论】:

  • 谢谢,下班后我会花时间查看并测试一下。感谢您的帮助!
  • 使用我的初始数据集,这非常有效,但在扩大信息范围后,我发现创建了许多重叠的元组。我相信这是因为我们不会循环,直到无法制作更多的配对。有什么建议吗?
  • @nghs 这有点奇怪。我的策略应该在第一次通过时将一个区域中的所有数据组合在一起。但是您确实必须将排序数据传递给它,如我的随机数据示例所示。
  • @nghs 如果您的数据排序,请将其粘贴到您的问题中,我会查看它。顺便说一句,Python 的sort 函数非常好,并且针对已经排序的数据中的子序列进行了优化。
  • 你说得对,我从已排序的数据集切换到未排序的数据集,现在我已经对其进行了排序。
【解决方案2】:

我认为您只想要具有&lt; 0.03 差异的组合:

from itertools import combinations
a = [1.05, 1.07, 1.18, 1.19, 1.22, 1.26, 1.30, 1.32]
result = [i for i in combinations(a, 2) if abs(i[0]-i[1]) < 0.03]

【讨论】:

  • 您的结果与 OP 的结果完全不同:它没有 (1.22, 1.18)
  • 这肯定是比我一直在做的配对更清洁的方法,但我也想循环遍历它,将一个区域内的所有列表组合在一起,直到不再配对。根据 cmets 的讨论,我刚才扩展了这个问题。感谢您的帮助!
  • @PM2Ring 是的,如果我正确理解了这个解决方案,它只涵盖了第一步,但这是我一直在做的第一步更简洁的方法,所以虽然不是“正确的答案” ',它确实有帮助!解锁权限后我会投票。
  • 我知道,但他的循环似乎是为了这个结果:)
  • @nghs combinations 是一个非常方便的功能,我经常使用它,但将它用于此特定任务并不是一个好主意。我们只需要比较列表中的相邻项目,而不是每一对。如果列表有 101 项,则 zipa 的代码生成并测试 101*100/2=5050 对,但我们实际上只需要执行 100 次测试。
猜你喜欢
  • 2018-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-31
  • 2018-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多