在每一行中,我如何编写一个python脚本来查找包含大于1.5的最连续值的集合?

idfiyjo8  于 2023-01-01  发布在  Python
关注(0)|答案(1)|浏览(111)

我想扫描一个大的excel文件。我有99列和20 k行。例如:This is one of rows:
有三组连续值大于1.5
连续大于1.5的值最多的是31,我的问题是如何编写一个python脚本来扫描整个文件,并找到每行中包含连续大于1.5的值最多的集合?
我需要一些帮助使用python脚本。谢谢。
我厌倦了这个,它只给予我5的连续值。但我需要最多/最大计数。

from itertools import tee, islice

def find_consecutive(the_list, threshold, count=5):
    my_iters = tee(the_list, count)
    for i, it in enumerate(my_iters):
        next(islice(it, i, i), None)
    return (f for f in zip(*my_iters) if all(x > threshold for x in f))

my_list = [0.2, 0.1, 0.3, 1.1, 0.7, 0.5, 1.2, 1.3, 1.4, 1.2, 1.9, 1.1, 0.2, 1.3, 1.5, 1.4, 1.2, 1.1, 0.2, 1.3, 0.1, 1.6, 0.2, 0.5, 1.0, 1.1, 0.2]
list(find_consecutive(my_list, 1.0))
laawzig2

laawzig21#

如果我理解正确的话,您可以使用groupby将列表分成大于1.5的值组,然后计算每组的项数,并保留最大的项

max(((l:=list(it), len(l)) for (yesno,it) in itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5) if yesno), key=lambda p:p[1])

给出了一个对子列表(枚举的,所以对(索引,元素))及其长度。
让我们看看它是如何在下面的列表中工作的

my_list=[1, 2, 3, 4, 1, 1, 0, 0, 6, 7, 8, 9, 8, 0, 0, 0, 1, 2, 2, 2, 1, 0]

(有3个数列〉1.5:从索引1开始的2、3、4,从索引8开始的6、7、8、9、8,以及从索引17开始的2、2、2。我们期望答案是第二个)。
我们从枚举列表开始,因为在最后,你需要解决方案的索引(你没有清楚地说出来,但是你的例子是这样描述的)。

list(enumerate(my_list))

[(0, 1), (1, 2), (2, 3), (3, 4), (4, 1), (5, 1), (6, 0), (7, 0), (8, 6), (9, 7), (10, 8), (11, 9), (12, 8), (13, 0), (14, 0), (15, 0), (16, 1), (17, 2), (18, 2), (19, 2), (20, 1), (21, 0)]

(Note这个答案的形式我使用list(...)[...]列表解析来展示中间结果,但大多数情况下,我不需要构建列表,所以在下一步中,我删除list()或用()生成器解析替换[]列表解析,这里enumerate将在下一步中直接传递给groupby。一般来说,除了显示结果,我避免构建显式列表,即使用内存,当生成器可以做的时候)
现在,我们可以使用groupby将枚举的可迭代对象拆分为〉1.5或〈= 1.5的值组

list(itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5))
[(False, <itertools._grouper object at 0x7fe9d250e3a0>), (True, <itertools._grouper object at 0x7fe9d250e1f0>), (False, <itertools._grouper object at 0x7fe9d250ecd0>), (True, <itertools._grouper object at 0x7fe9d250e160>), (False, <itertools._grouper object at 0x7fe9d250eb20>), (True, <itertools._grouper object at 0x7fe9d250ebb0>), (False, <itertools._grouper object at 0x7fe9d250ec70>)]

是一个布尔值/迭代器对的列表,布尔值是lambda在子群的所有元素上的结果,所以对于小于等于1.5的子群为False,对于大于1.5的子群为True,迭代器是迭代每个子群的迭代器。
我们只对"真"值感兴趣,即分组值〉1.5

[it for yesno,it in itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5) if yesno]
[<itertools._grouper object at 0x7fe9d250eeb0>, <itertools._grouper object at 0x7fe9d250ef40>, <itertools._grouper object at 0x7fe9d250e0d0>]

是每个值大于1.5的子列表的迭代器。毫不奇怪,在我的例子中有3个。为了演示,我们可以展示它们的内容

[list(it) for yesno,it in itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5) if yesno]

[[(1, 2), (2, 3), (3, 4)], 
 [(8, 6), (9, 7), (10, 8), (11, 9), (12, 8)], 
 [(17, 2), (18, 2), (19, 2)]]

正如预期的那样,我们有3个序列:一个索引为1,2,3,值为2,3,4;另一个索引为8 → 12,值为6、7、8、9、8,最后一个索引为17、18、19,值为2、2、2
我们感兴趣的是每个子组的大小,而不仅仅是它们的内容,我们可以计算len,为了避免迭代两次,我使用:=操作符将列表放入变量中

[(l:=list(it), len(l)) for (yesno,it) in itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5) if yesno]

因此代码与前面相同,但使用(l:=list(it), len(l))对,而不是仅使用list(it)

[([(1, 2), (2, 3), (3, 4)], 3), 
 ([(8, 6), (9, 7), (10, 8), (11, 9), (12, 8)], 5), 
 ([(17, 2), (18, 2), (19, 2)], 3)]

因此,结果与之前相同,但配对包含之前的序列及其长度
差不多了。现在我们只需要保留最大的值。max就可以完成这个任务。但是我们需要说明应该比较什么来帮助它。这里的最大值是长度最大的值,也就是对中最大的第二个值。因此得到了结果

max(((l:=list(it), len(l)) for (yesno,it) in itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5) if yesno), key=lambda p:p[1])

([(8, 6), (9, 7), (10, 8), (11, 9), (12, 8)], 5)

lambda p:p[1]的Angular 来看,这是最大值。
如果您只需要索引,现在只需选择它即可

max(((l:=list(it), len(l)) for (yesno,it) in itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5) if yesno), key=lambda p:p[1])[0][0][0]

返回8
每个人都喜欢一行程序,但是这一行程序可能需要被分解成更小的部分,因为如果my_list为空或者my_list不包含任何大于1.5的值,将会发生什么(如果你确信它不会发生,那么这一行程序就是一件确定的事情:只要max返回了一些东西,它就是一个对,所以第一个[0]是有效的,这个对的第一部分是一个序列,这个序列不能为空(groupby从不创建空子序列),所以[0][0]也是有效的,它返回这个序列的第一个元素,这是一个enumerate的元素,它也是一个对,所以[0][0][0]是有效的。所以,这里没有索引错误的风险。但是如果列表为空,max可能会失败。
有两种解决方案,一种是先建立一个序列列表,然后计算max

def maxSeq(my_list):
    seqs=[(l:=list(it), len(l)) for (yesno,it) in itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5) if yesno]
    if len(seqs)==0:
        return None
    else:
        return max(seqs, key=lambda p:p[1])

缺点是,当以前的版本只有生成器(和列表,但仅用于子序列)时,它强制计算实际的列表(seqs)
或者您可以使用try/except

def maxSeq(my_list):
    try:
        return max(((l:=list(it), len(l)) for (yesno,it) in itertools.groupby(enumerate(my_list), lambda p: p[1]>1.5) if yesno), key=lambda p:p[1])[0][0][0]
    except:
        return None

或者,您可以向列表中添加一个标记,以确保max参数永远不为空

max(((l:=list(it), len(l)) for (yesno,it) in itertools.groupby(enumerate(my_list+[0,2]), lambda p: p[1]>1.5) if yesno), key=lambda p:p[1])[0][0][0]

例如,不能失败(在最坏的情况下,它将返回最后一个2的索引)

相关问题