计算两个列表项之间的因子差异

4

我有一个问题,但找不到答案。我的Python知识较基础,目前使用版本为2.7.2和2.6.5。

假设我有以下列表:

list1 = [1642842,780497,1506284,1438592,1266530,1154853,965861,610252,1091847,1209404,1128111,749998]

我想知道每两个项目之间的因子差异(第0,1项,第1,2项,第2,3项等)。

输出应该像这样(但最好四舍五入到小数点后一位):

list2 = [2.1048665145,0.5181605859,1.047054342,1.1358530789,1.0967023509,1.195672048, 1.5827248415,0.5589171377,0.9027975763,1.0720611713,1.5041520111]

我需要的最终结果是:当因子大于1.5时,我想报告2个列表项的编号及其因子值。
列表项0,1 值为2.1
列表项6,7 值为1.6
列表项10,11 值为1.5
我该如何做?
可以使用以下代码轻松找到数字差异:
print numpy.diff(list1)

或者

for i in (abs(x - y) for (x, y) in zip(list1[1:], list1[:-1])):
    print i

但是我正在努力寻找解决上述问题的方法?我尝试了一些上面的代码,但似乎无法得到好结果。

还要注意的是,虽然我将首先过滤列表1中的数据,但它将包含导致我之前出现除以零问题的后续零值。

编辑:感谢解决方案,它们中的大多数都能够完全符合我的要求。不幸的是,这些列表中的项目有一个固定的位置。我不能丢弃这些信息,因此过滤掉列表中的某些项目以防止出现“ZeroDivisionError: float division by zero”等错误并不是真正的选择。为了更好地解释一下,可能会有以下格式的列表:

list1 = [0,0,0,0,0,0,0,0,2,5,65,456,456456,456564,456666,666666,2344,233,232,122,88,6,0,0,0,0]

以下是关于解决此问题的Pythonic方法的任意解决方案,请注意输出格式:

第0个项目,第1个项目的值为0

第1个项目,第2个项目的值为0

第2个项目,第3个项目的值为0

等等。

第8个项目,第9个项目的值为2.5

第9个项目,第10个项目的值为13

等等。

最后编辑:无论如何,我都会过滤数据,而不是创建问题以修复它们。感谢所有答案!

5个回答

4

使用itertools中的pairwise函数:

import itertools

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = itertools.tee(iterable)
    next(b, None)
    return itertools.izip(a, b)

diff = [round(abs(x/float(y)), 1) for x, y in pairwise(your_iterable)]

谢谢提醒,但这对于这个任务来说有点过头了吧? - Roman Pekar
我认为这个解决方案特别易读,而且 pairwise 是一个相当通用的函数,可能在其他地方也有用。人们可以立即看出它是做什么的以及如何工作的。对于其他答案,我不能说同样的话。如果您将最后一个列表推导式替换为生成器,则此答案也适用于可迭代对象而无需列表开销。 - D K

1
一种可能的方式:

list1 = [1642842,780497,1506284,1438592,1266530,1154853,965861,610252,1091847,1209404,1128111,749998]
list2 = [(i, a, b, (1.0*a)/b) for (i, (a, b)) in enumerate(zip(list1, list1[1:]))]
for i, a, b, f in filter(lambda (i, a, b, f): f > 1.5, list2):
    print 'item {0} ({1}), {2} ({3}) value {4:.1f}'.format(i, a, i+1, b, f)

输出:

item 0 (1642842), 1 (780497) value 2.1
item 6 (965861), 7 (610252) value 1.6
item 10 (1128111), 11 (749998) value 1.5

1
>>> g = ((i, i + 1, round(1.0 * list1[i] / list1[i + 1], 2)) for i in range(len(list1) - 1))
>>> print [x for x in g if x[2] >= 1.5]
[(0, 1, 2.1), (6, 7, 1.58), (10, 11, 1.5)]

或者

>>> g1 = ((i, i + 1) for i in range(len(list1) - 1))
>>> g2 = ((x, y, round(float(list1[x]) / list1[y], 2)) for x, y in g1)
>>> print [x for x in g2 if x[2] >= 1.5]
[(0, 1, 2.1), (6, 7, 1.58), (10, 11, 1.5)]

1

也可以查看这个解决方案:

a = [..., ..., ]

for i,v in enumerate(map(lambda t: float(t[0])/float(t[1]), zip(a, a[1:]))):
    print "{0},{1} - {2:.1f}".format(i,i+1,v)

测试:

>>> a
[24144, 24666, 10421, 28925, 23619, 13703, 20766, 10029, 23655, 22183]
>>> for i,v in enumerate(map(lambda t: float(t[0])/float(t[1]), zip(a, a[1:]))):
...     print "{0},{1} - {2:.1f}".format(i,i+1,v)
...
0,1 - 1.0
1,2 - 2.4
2,3 - 0.4
3,4 - 1.2
4,5 - 1.7
5,6 - 0.7
6,7 - 2.1
7,8 - 0.4
8,9 - 1.1
>>>

转换:enumerate 用于在 for 循环中访问索引,map 用于执行列表上的函数,lambda 用于定义函数,zip 用于从初始列表形成数组对。 - rook

0

关于什么?

  for i in (float(x)/y if x > y else float(y)/x for (x, y) in zip(list1[1:], list1[:-1])):
      print i

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