如果超过某个值,计算元素数量

3

我有一组带有浮点类型值的元素列表。我想要迭代这些元素并计算它们是否超过某个值,但只有当它们出现在阈值以上的最小计数时才计算。例如,如果我有以下输入:

list_of_values = [2.0, 2.0, 2.0, 2.0, 0, 0, 2.0, 2.0, 2.0, 0, 0]
treshold_value = 1.0
minimum_count = 4

答案应该是4,因为阈值1.0仅在索引0-3连续超过4次。现在我有以下代码,
for value in list_of_values:
    if value >= treshold_value:
        counter += 1
    if counter >= (minimum_count):
        time_use += 1
    if value < min_treshold_value:
        counter = 0
print(time_use)

我知道应该有一些Pythonic的方法来实现这个:)
编辑:应计算超过阈值的所有连续子序列值的总和。

如果 list_of_values 的第一项是 1.0,那么结果应该是什么? - RomanPerekhrest
如果有多个符合条件的数字串,例如 [2.0, 2.0, 2.0, 2.0, 0, 0, 3.0, 2.0, 2.0, 2.0, 10.0, 0, 0],那么结果应该是4、5还是9呢? - mhawke
那么这是超过“threshold”的最常出现的值的最后一次出现的索引吗? - Eric Duminil
@ConSod:那么为什么在mhawke的例子中应该是9呢? - Eric Duminil
抱歉我的解释不够清楚,@EricDuminil。重要的是,只要有至少minimum_count个值相邻且它们的值大于等于treshold_value,那么这些值的具体数值并不重要。 - ConSod
显示剩余6条评论
4个回答

2
以下是对于使用条件生成器和适当的键函数与 maxgroupby 的示例代码:
from itertools import groupby

len(max((list(g) for k, g in groupby(list_ov, key=lambda x: x > threshold) if k), key=len))

groupby函数可以根据键函数将可迭代对象中连续相同的值分组。它会生成键值和相应子可迭代对象的一对对。


2
LOL,和妻子和母亲一起度假徒步旅行...无聊死了,正在手机应用程序上发布:D一定要勾选维基框。 - user2390182
哈哈,好好享受和夫人在一起的时光。 - cs95
这个答案需要一些解释,以便更有帮助那些不知道 groupby() 等函数的人。 - mhawke
我该如何更改代码以便对所有超过阈值的子序列求和?我尝试删除了max()函数。您能否简要解释一下这是如何工作的?这很棒,我理解列表推导式,但我不理解这是如何工作的 :) - ConSod
@ConSod sum(len(g) for k, g ...) 没有 max 的关键参数(因为不再有 max 调用) - user2390182
显示剩余3条评论

1
你可以使用 itertools.groupby() 来帮助:
from itertools import groupby

def count_runs(list_of_values, threshold_value=1.0, minimum_count=4):
    count = 0
    for k, g in groupby(list_of_values, key=lambda x: x >= threshold_value):
        if k:
            g = list(g)
            if len(g) >= minimum_count:
                count += len(g)
    return count

>>> count_runs([2.0, 2.0, 2.0, 0.0, 0, 0, 2.0, 2.0, 2.0, 0, 0])
0
>>> count_runs([2.0, 2.0, 2.0, 2.0, 0, 0, 2.0, 2.0, 2.0, 0, 0])
4
>>> count_runs([2.0, 2.0, 2.0, 2.0, 0, 0, 3.0, 2.0, 2.0, 2.0, 10.0, 0, 0])
9

这将提供在每个包含minimum_count个或更多值的组中超过阈值的值的计数。请注意,它处理符合标准的多个组。 例如,上一个示例的groupby()将返回以下内容:
>>> list_of_values = [2.0, 2.0, 2.0, 2.0, 0, 0, 3.0, 2.0, 2.0, 2.0, 10.0, 0, 0]
>>> for k, g in groupby(list_of_values, key=lambda x: x >= threshold_value):
...     print(k, list(g))
... 
True [2.0, 2.0, 2.0, 2.0]
False [0, 0]
True [3.0, 2.0, 2.0, 2.0, 10.0]
False [0, 0]

任何一个包含1个或更多的值且大于等于阈值的组将出现在键为True的组中。只有长度大于等于最小计数的组才会进一步考虑,其中它的长度将与其他这样的组一起计算。
这段代码可以更简洁地编写,但可读性会降低,如下所示:
def count_runs(list_of_values, threshold_value=1.0, minimum_count=4):
    return sum(count for count in (len(list(g)) for k, g in groupby(list_of_values, key=lambda x: x >= threshold_value) if k) if count >= minimum_count)

0
只需遍历列表并创建一个字典,其中键=浮点数,值=您遇到此数字的次数。并且仅将大于阈值的浮点数添加到字典中。就像这样:
d = {}
for f in   list_of_values :
    if f > treshold:
        if d.get(f,False):
             d[f] +=1
        else:
             d[f] = 1
max = 0
for k,v in d.iteritems():
    if v> max:
        max = v

return max

你的一个for循环语句也存在语法问题。 - cs95

0

看起来你不关心顺序。在这种情况下,groupby 不正确,因为它只能对相邻的元素进行分组。

你可以使用 Counter 和两个列表推导式来过滤值:

list_of_values = [2.0, 2.0, 2.0, 2.0, 0, 0, 3.0, 2.0, 2.0, 2.0, 10.0, 0, 0]
threshold_value = 1.0
minimum_count = 4

from collections import Counter
counter = Counter([x for x in list_of_values if x > threshold_value])
print(counter)
# Counter({2.0: 7, 3.0: 1, 10.0: 1})
print([(x, count) for x, count in counter.items() if count > minimum_count])
# [(2.0, 7)]

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