我有一个元组列表,如下所示:
data = [
('A', '59', '62'), ('A', '2', '6'), ('A', '87', '92'),
('A', '98', '104'), ('A', '111', '117'),
('B', '66', '71'), ('B', '25', '31'), ('B', '34', '40'), ('B', '46', '53'),
('B', '245', '251'), ('B', '235', '239'), ('B', '224', '229'), ('B', '135', '140'),
('C', '157', '162'), ('C', '203', '208'),
('D', '166', '173'), ('D', '176', '183'),
('E', '59', '62'), ('E', '2', '6'), ('E', '87', '92'), ('E', '98', '104'), ('E', '111', '117')
]
它们对应于更大数据集的子集,因此我按上述进行提取以简化本文。每个元组的第一个元素(即A,B,C,D,E ...)都是一个标识符,并且可以出现在多个副本中。
我想提取每个ID /类别(A,B,C,D,E ...):
1-元组的第二个元素中的最小值
2-元组的第三个元素的最大值
最终输出列表应如下所示:
A: min = 2, max = 117
B: min = 25, max = 251
C: min = 157, max = 208
D: min = 166, max = 183
E: min = 2, max = 117
我尝试了一种基于以下信息的方法:How to remove duplicate from list of tuple when order is important
我简化了测试,只使用了前两个元素的元组并仅提取了最小值。
输出看起来像这样:
('A', '111')
('B', '135')
('C', '157')
('D', '166')
('E', '111')
应该是:
('A', '2')
('B', '25')
('C', '157')
('D', '166')
('E', '2')
我正在寻找一种适用于完整的“三元组”示例的方法,以避免将数据拆分为多个子集。
非常感谢您的宝贵时间。
你好
请在下面查看我的修改,其中包括之前未包含的代码段。这会在帖子的前部分给出错误的最小值。
data_min_only = [('A', '59'), ('A', '2'), ('A', '87'), ('A', '98'), ('A', '111'), ('B', '66'), ('B', '25'), ('B', '34'), ('B', '46'), ('B', '245'), ('B', '235'), ('B', '224'), ('B', '135'), ('C', '157'), ('C', '203'), ('D', '166'), ('D', '176'), ('E', '59'), ('E', '2'), ('E', '87'), ('E', '98'), ('E', '111')]
from collections import OrderedDict
empty_dict = OrderedDict()
for item in data_min_only:
# Get old value in dictionary if exist
old = empty_dict.get(item[0])
# Skip if new item is larger than old
if old:
if item[1] > old[1]:
continue
else:
del d[item[0]]
# Assign
empty_dict[item[0]] = item
list(empty_dict.values())
我当时以为每个类别的元组值的顺序都是问题(在遍历data_min_only
之前应该从最小到最大。
感谢所有张贴者的迅速回应和建议/解决方案!我目前正在努力解决这些问题,以尝试进一步理解和适应它们。
我调整了@slider建议,以检索最小和最大之间的差异。我还尝试将结果输出到如下列表中,但是仅显示最后一个结果。
for k, g in groupby(sorted(data), key=lambda x: x[0]):
vals = [(int(t[1]), int(t[2])) for t in g]
print (max(i[1] for i in vals) - min(i[0] for i in vals))
test_lst = []
test_lst.append((max(i[1] for i in vals) - min(i[0] for i in vals)))
我也尝试过,但是得到了相同的结果:
for i in vals:
test_lst2 = []
test_lst2.append((max(i[1] for i in vals) - min(i[0] for i in vals)))
对于这种循环,将结果提取到列表的最佳方法是什么?
再次感谢。
test_lst = []
for k, g in groupby(sorted(data), key=lambda x: x[0]):
vals = [(int(t[1]), int(t[2])) for t in g]
print (max(i[1] for i in vals) - min(i[0] for i in vals))
test_lst.append((max(i[1] for i in vals) - min(i[0] for i in vals)))
提取循环数据的解决方案-空列表应在循环之外。请在下面查看@slider的评论。
答案 0 :(得分:5)
您可以使用itertools.groupby
通过“ id”键首先进行分组,然后计算每组的最小值和最大值:
from itertools import groupby
groups = []
for k, g in groupby(sorted(data), key=lambda x: x[0]):
groups.append(list(g))
for g in groups:
print(g[0][0], 'min:', min(int(i[1]) for i in g), 'max:', max(int(i[2]) for i in g))
输出
A min: 2 max: 117
B min: 25 max: 251
C min: 157 max: 208
D min: 166 max: 183
E min: 2 max: 117
请注意,您不必先将组存储在groups
列表中;您可以在groupby
for循环中迭代时直接打印最小值和最大值:
for k, g in groupby(sorted(data), key=lambda x: x[0]):
vals = [(int(t[1]), int(t[2])) for t in g]
print(k, 'min:', min(i[0] for i in vals), 'max:', max(i[1] for i in vals))
答案 1 :(得分:2)
data = [('A', '59', '62'), ('A', '2', '6'), ('A', '87', '92'), ('A', '98', '104'), ('A', '111', '117'), ('B', '66', '71'), ('B', '25', '31'), ('B', '34', '40'), ('B', '46', '53'), ('B', '245', '251'), ('B', '235', '239'), ('B', '224', '229'), ('B', '135', '140'), ('C', '157', '162'), ('C', '203', '208'), ('D', '166', '173'), ('D', '176', '183'), ('E', '59', '62'), ('E', '2', '6'), ('E', '87', '92'), ('E', '98', '104'), ('E', '111', '117')]
result = {} # construct result dictionary
for i in data:
cur_min, cur_max = map(int, i[1:])
min_i, max_i = result.setdefault(i[0], [cur_min, cur_max])
if cur_min < min_i:
result[i[0]][0] = cur_min
if cur_max > max_i:
result[i[0]][1] = cur_max
# print(result) # dictionary containing keys with list of min and max values for given key >>> {'A': [2, 117], 'B': [25, 251], 'C': [157, 208], 'D': [166, 183], 'E': [2, 117]}
for k, v in result.items(): # loop to print output
print("{} min: {} max: {}".format(k, v[0], v[1]))
A min: 2 max: 117
B min: 25 max: 251
C min: 157 max: 208
D min: 166 max: 183
E min: 2 max: 117
答案 2 :(得分:1)
另一种方法:
max_list = {}
min_list = {}
for i in data:
if i[0] not in max_list:
max_list[i[0]] = -99999
min_list[i[0]] = 99999
if max_list[i[0]] < int(i[2]):
max_list[i[0]] = int(i[2])
if min_list[i[0]] > int(i[1]):
min_list[i[0]] = int(i[1])
for ele in max_list:
print(ele, ' min: ', min_list[ele], 'max: ', max_list[ele])
答案 3 :(得分:1)
这是另一种可以使用Pandas库工作的方法:
import numpy as np
import pandas as pd
#The same dataset you provided us
data = [('A', '59', '62'), ('A', '2', '6'), ('A', '87', '92'), ('A', '98', '104'), ('A', '111', '117'), ('B', '66', '71'), ('B', '25', '31'), ('B', '34', '40'), ('B', '46', '53'), ('B', '245', '251'), ('B', '235', '239'), ('B', '224', '229'), ('B', '135', '140'), ('C', '157', '162'), ('C', '203', '208'), ('D', '166', '173'), ('D', '176', '183'), ('E', '59', '62'), ('E', '2', '6'), ('E', '87', '92'), ('E', '98', '104'), ('E', '111', '117')]
#Generate dataframe df
df = pd.DataFrame(data=data)
#Convert strings to their respective numerical values
df[[1,2]] = df[[1,2]].apply(pd.to_numeric, errors='ignore')
#Group values using column 0
df.groupby(0).agg({1: min, 2: max})
我们使用agg方法和字典作为参数,以便为每个分组范围找到第1列中的最小值和第2列中的最大值。
这将产生以下结果:
1 2
0
A 2 117
B 25 251
C 157 208
D 166 183
E 2 117