Python—在2D列表中选择总计为累积总和68%的元素
我在二维列表中有我的值Python—在2D列表中选择总计为累积总和68%的元素,python,sorting,Python,Sorting,我在二维列表中有我的值 a = [[5,2],[7,4],[0,3]] 多亏了这个问题的答案 我设法按降序对它们进行排序,得到了上一个列表中的值的坐标 from operator import itemgetter b = [((i, j), v) for i, t in enumerate(a) for j, v in enumerate(t)] b.sort(key=itemgetter(-1), reverse=True) print(b) coords, vals = zip(*b)
a = [[5,2],[7,4],[0,3]]
多亏了这个问题的答案
我设法按降序对它们进行排序,得到了上一个列表中的值的坐标
from operator import itemgetter
b = [((i, j), v) for i, t in enumerate(a) for j, v in enumerate(t)]
b.sort(key=itemgetter(-1), reverse=True)
print(b)
coords, vals = zip(*b)
print(vals)
print(coords)
输出:
[((1, 0), 7), ((0, 0), 5), ((1, 1), 4), ((2, 1), 3), ((0, 1), 2), ((2, 0), 0)]
(7, 5, 4, 3, 2, 0)
((1, 0), (0, 0), (1, 1), (2, 1), (0, 1), (2, 0))
现在我需要首先计算元素的总累积和,我使用
cumulative_sum = np.cumsum(a)
然后,我需要开始对有序元素求和,直到它们达到某个值,即累积总和的68%。在这种情况下,这意味着执行以下逻辑操作:
1) 累计总和=5+2+7+4+0+3=21
2) 累计金额的68%=14.28
3) 然后开始求和:7+5+4+。。。然后选择相对元素,直到它们超过14.28(在这个简化示例中,仅选择值7和5)
4) 在所选元素中,我需要获得数组a
(在这种情况下,
(1,0)
和(0,0)
)使用一个简单的for
循环来迭代b
中的(坐标、值)对,这很容易做到。诀窍是在我们将坐标元组t
添加到selected
中的坐标列表之前,测试总和是否会溢出所需的限制
from operator import itemgetter
a = [[5,2],[7,4],[0,3]]
b = [((i, j), v) for i, t in enumerate(a) for j, v in enumerate(t)]
b.sort(key=itemgetter(-1), reverse=True)
coords, vals = zip(*b)
total = sum(vals)
lim = int(0.68 * total)
selected = []
s = 0
for t, v in b:
if s + v <= lim:
s += v
selected.append(t)
else:
break
print(s, selected)
极限计算可以写成
lim = 0.68 * total
但是,如果您的数据保证是整数,那么将lim
也作为一个整数就更整洁了,因为比较两个整数要比比较一个整数和一个浮点稍微高效一些。当您执行将int与float(包括比较)组合的操作时,必须将它们转换为公共类型才能执行该操作
这里有一个替代版本,如评论中所讨论的。它在
vals
中的值上循环,直到达到所需的总和,跟踪vals
中的索引。然后,它使用该索引将使用的值和相应的坐标元组从b
列表切片到新的selected
列表中(这与以前版本的selected
列表不同)
谢谢。幸运的是,我的数据不是整数,实际上它们是非常小的数字,因此我不应该使用lim作为整数。我如何提取这些坐标对,我的意思是如何安排代码,使其自动存储[1][0]和[0][0](如示例所示,但通常所有占总数68%的值)在一个新列表中?@johnhenry您可以使用与我们将坐标保存到
所选列表中相同的方法来执行此操作。在循环外部初始化空列表,例如values=[]
。然后在循环中执行值。在选定的行之前或之后追加(v)
。追加(t)
行。谢谢,尽管我的问题有点复杂。实际上,我必须绘制与网格上的坐标相关联的值a[1][0]和a[0][0]。您的解决方案输出的元组给我带来了困难,因为我无法再次使用它们来选择要发送到的数组元素plotting@johnhenry对不起,我不太明白这个问题。如果您有一个坐标元组,例如t=(2,1)
您可以执行a[t[0]][t[1]]
来获得a[2][1]
。但是,如果创建我前面的评论中描述的值
列表,则不需要这样做,因为该列表中的每个项都对应于所选
列表中的坐标元组。另一个选项是修改我的答案中的代码,这样它就可以在b
数组中找到对应于所选组件末尾的索引。我将添加更多代码来解释我的意思。
lim = 0.68 * total
from operator import itemgetter
a = [[5, 2], [7, 4], [0, 3]]
b = [((i, j), v) for i, t in enumerate(a) for j, v in enumerate(t)]
b.sort(key=itemgetter(-1), reverse=True)
coords, vals = zip(*b)
lim = 0.68 * sum(vals)
s = 0
for i, v in enumerate(vals):
if s + v <= lim:
s += v
else:
break
selected = b[:i]
print(i, selected)
for (i, j), v in selected:
print(i, j, v)
2 [((1, 0), 7), ((0, 0), 5)]
1 0 7
0 0 5