将元组列表筛选以包含最大值和最小值

3
我已经生成了一个元组的长列表(格式如下)。列表中的每个元组都有时间作为第一个元素和事件作为第三个成员。第二个成员始终相同,以识别来自其他类似列表的列表,我将不得不处理它们。元组具有许多不同的第三个元素,并且每个元素在不同值的时间(即第一个元素)上有多个条目。
我正在尝试过滤列表,以删除每个事件(元组的第三个成员)的最小和最大时间值之外的所有内容。我尝试使用列表理解,但很快就感到困惑。
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP1_G1.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP1_G1.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP1_G1.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP1_G1.575')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3567', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3600', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3800', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3800', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3800', 'VOLTAGE DEVIATION', 'HORIZ_G .575')
('1.3800', 'VOLTAGE DEVIATION', 'MEDBOWCO 115')
('1.3800', 'VOLTAGE DEVIATION', 'MEDBOWCO 115')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
'1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4267', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4267', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4267', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4267', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4267', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4833', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4833', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4833', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4833', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4833', 'VOLTAGE DEVIATION', 'HIPLN_G .575')

过滤后的结果为:

('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP2G23.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP1_G1.575')
('1.3467', 'VOLTAGE DEVIATION', 'DNLP1_G1.575')
('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3600', 'VOLTAGE DEVIATION', 'DIFICULT 230')
('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3800', 'VOLTAGE DEVIATION', '7MIHL G1.575')
('1.3800', 'VOLTAGE DEVIATION', 'HORIZ_G .575')
('1.3800', 'VOLTAGE DEVIATION', 'MEDBOWCO 115')
('1.3800', 'VOLTAGE DEVIATION', 'MEDBOWCO 115')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230')
('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5')
('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5')
'1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4267', 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575')
('1.4833', 'VOLTAGE DEVIATION', 'HIPLN_G .575')`

我正在尝试下面的代码,但是出现了错误。由于我对此比较新,请告诉我是否有做错了什么。代码中的 m1 是通过 findall 生成的元组列表。我已经在代码顶部导入了 ast。

       m1 = re.findall(pattern1,wholefile)
       m1=[ast.literal_eval(t) for t in m1] 
       m1=[(float(a),b,c) for a,b,c in m1] 
       keys=sorted({t[2] for t in m1}) 
       for key in keys: 
           group=filter(lambda t: t[2]==key,m1)
           print '{}:\n\tmax: {}\n\tmin: {}'.format(key,max(group),min(group))

1
你遇到了什么错误?也许是在“1.4233”之前缺少了开括号。 - dawg
我使用Python 2.7再次运行,没有任何问题。之前我在运行Python 2.5时,Pywin32模块出现了其他问题。这会是Python 2.5的问题吗? - user1642486
还有一个问题。如果我想将最大和最小时间分配给变量(比如t1max和t1min),以便我可以计算持续时间(t1max-t1min),那么在for循环中是不是应该使用t1max = max(group)? - user1642486
4个回答

4
重新将元组转换为字典可以使生活更加轻松。
from collections import defaultdict

d = defaultdict(list)
for t,_,v in your_tuple_list:
     d[v].append(t)

在此之后,d将为每个事件拥有一个键,并且该时间段内的相关时间列表。

它的显示效果如下(有点类似):

>>> d['DNLP2G23.575']
['1.3433'....]

现在问题变成了找到每个列表的最小值和最大值;使用min()max()很容易解决这个问题。
一旦你完成了这些步骤,你就可以按照自己想要的顺序得到数据集,并将其转换回元组/列表等格式。
如果你愿意,你可以将列表转换为set,这样可以消除重复的时间戳,并通过加速计算最小值/最大值来节省时间,特别是当你需要处理一个包含大量元组的列表时。
你还应该将时间戳转换为float类型 - 你可以在主循环中进行: d[v].append(float(t))。这是为了确保max()min()函数的正确运行。

3

使用itertools.groupby实现此功能:

>>> import itertools
>>> import operator
>>> results = []
>>> for key, group in itertools.groupby(tuplelist, operator.itemgetter(2)):
...    group = list(group)
...    results.append(min(group))
...    results.append(max(group))
...
>>> pprint.pprint(results)
[('1.3433', 'VOLTAGE DEVIATION', 'DNLP2G23.575'),
 ('1.3467', 'VOLTAGE DEVIATION', 'DNLP2G23.575'),
 ('1.3467', 'VOLTAGE DEVIATION', 'DNLP1_G1.575'),
 ('1.3467', 'VOLTAGE DEVIATION', 'DNLP1_G1.575'),
 ('1.3533', 'VOLTAGE DEVIATION', 'DIFICULT 230'),
 ('1.3600', 'VOLTAGE DEVIATION', 'DIFICULT 230'),
 ('1.3600', 'VOLTAGE DEVIATION', '7MIHL G1.575'),
 ('1.3800', 'VOLTAGE DEVIATION', '7MIHL G1.575'),
 ('1.3800', 'VOLTAGE DEVIATION', 'HORIZ_G .575'),
 ('1.3800', 'VOLTAGE DEVIATION', 'HORIZ_G .575'),
 ('1.3800', 'VOLTAGE DEVIATION', 'MEDBOWCO 115'),
 ('1.3800', 'VOLTAGE DEVIATION', 'MEDBOWCO 115'),
 ('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230'),
 ('1.3800', 'VOLTAGE DEVIATION', 'STNDPSVC 230'),
 ('1.3867', 'VOLTAGE DEVIATION', 'MINERS  34.5'),
 ('1.3900', 'VOLTAGE DEVIATION', 'MINERS  34.5'),
 ('1.4233', 'VOLTAGE DEVIATION', 'FT CRK2 34.5'),
 ('1.4267', 'VOLTAGE DEVIATION', 'FT CRK2 34.5'),
 ('1.4800', 'VOLTAGE DEVIATION', 'HIPLN_G .575'),
 ('1.4833', 'VOLTAGE DEVIATION', 'HIPLN_G .575')]

注意:

  1. 最小值/最大值是按顺序对元组的元素进行操作。然而,第一个元素实际上是一个字符串而不是浮点数,因此您可能需要传递key参数给min和max以使用不同的值。
  2. 这仅在分组键的所有相同值都在列表中相邻的情况下才有效。在您的示例输出中,这是成立的,但如果不是,则可能需要先对列表进行排序。

+1也可以(不过在取最大值和最小值之前需要将其转换为float)。我能想到的唯一注意事项是这需要键入元素是连续的,而defaultdict方法则不需要。你可以进行排序来解决这个问题。 - DSM
所有相同的值总是在一起,因为它们代表线性时间。时间步长比这些数字小得多,所以它们看起来像重复,但它们都是不同的。分析是用更小的粒度完成的,但我的报告将使用打印的粒度。 - user1642486

1

只要您确实有一个以浮点数为第一个值的元组列表,这个方法就可以使用:

keys=sorted({t[2] for t in tups})
for key in keys:
    group=filter(lambda t: t[2]==key,tups)
    print '{}:\n\tmax: {}\n\tmin: {}'.format(key,max(group),min(group))

输出:

MIHL G1.575:
    max: (1.38, 'VOLTAGE DEVIATION', '7MIHL G1.575')
    min: (1.36, 'VOLTAGE DEVIATION', '7MIHL G1.575')
DIFICULT 230:
    max: (1.36, 'VOLTAGE DEVIATION', 'DIFICULT 230')
    min: (1.3533, 'VOLTAGE DEVIATION', 'DIFICULT 230')
DNLP1_G1.575:
    max: (1.3467, 'VOLTAGE DEVIATION', 'DNLP1_G1.575')
    min: (1.3467, 'VOLTAGE DEVIATION', 'DNLP1_G1.575')
DNLP2G23.575:
    max: (1.3467, 'VOLTAGE DEVIATION', 'DNLP2G23.575')
    min: (1.3433, 'VOLTAGE DEVIATION', 'DNLP2G23.575')
FT CRK2 34.5:
    max: (1.4267, 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
    min: (1.4233, 'VOLTAGE DEVIATION', 'FT CRK2 34.5')
HIPLN_G .575:
    max: (1.4833, 'VOLTAGE DEVIATION', 'HIPLN_G .575')
    min: (1.48, 'VOLTAGE DEVIATION', 'HIPLN_G .575')
HORIZ_G .575:
    max: (1.38, 'VOLTAGE DEVIATION', 'HORIZ_G .575')
    min: (1.38, 'VOLTAGE DEVIATION', 'HORIZ_G .575')
MEDBOWCO 115:
    max: (1.38, 'VOLTAGE DEVIATION', 'MEDBOWCO 115')
    min: (1.38, 'VOLTAGE DEVIATION', 'MEDBOWCO 115')
MINERS  34.5:
    max: (1.39, 'VOLTAGE DEVIATION', 'MINERS  34.5')
    min: (1.3867, 'VOLTAGE DEVIATION', 'MINERS  34.5')
STNDPSVC 230:
    max: (1.38, 'VOLTAGE DEVIATION', 'STNDPSVC 230')
    min: (1.38, 'VOLTAGE DEVIATION', 'STNDPSVC 230')

根据您的评论,看起来您确实有类似元组的文本。因此,要将其转换为实际的元组:
import ast

tups=[ast.literal_eval(t) for t in tups]
tups=[(float(a),b,c) for a,b,c in tups]

ast?使用csv读取会更好,避免不必要的评估。 - Burhan Khalid
@BurhanKhalid:你仍然需要处理CSV中的括号... 我删除了这部分,因为我主要是在处理问题的格式,而且不清楚他实际上是否有元组... - the wolf
元组列表是使用三个组进行查找后的结果。我将查找的结果分配给了我的元组列表。谢谢,我会尝试它们,看哪一个最适合我。 - user1642486
使用这个解决方案,我首先需要循环遍历列表并将所有第一个元组值转换为浮点数吗? - user1642486
@user1642486:你需要使用任何一种解决方案来完成这个任务。否则,你将得到词法最小值/最大值:如果你不将它们转换为浮点数,max('2','15')会产生'2'。 - the wolf

0

如果你只有少量的元组,那么这可能会过度杀伤,但是如果你有一个长列表并且能够使用外部库,那么可以看一下 pandas。假设包含元组的变量为 tuplelist,则以下代码将给出你想要的输出:

import pandas
df = pandas.DataFrame.from_records(tuplelist)
df = pandas.concat([df.groupby([1, 2]).min(), 
                df.groupby([1, 2]).max() ])
df = df.sort().reset_index().reindex(columns = [0,1,2])
print list(tuple(x) for x in df.values)

这看起来很有趣,但我不确定能否使用外部库。我会去了解一下。谢谢! - user1642486

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