我的值在一个二维列表中。
a = [[5,2],[7,4],[0,3]]
感谢这个问题的回答 sorting list of lists and getting indices in unsorted list 我设法按降序对它们进行排序,并获得了前一个列表中值的坐标。
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)
然后我需要开始对有序元素求和,直到它们达到某个值,即 cumulative_sum
的 68%。在这种情况下,这意味着执行以下逻辑操作:
1) 累积总和 = 5+2+7+4+0+3 = 21
2) cumulative_sum 的 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)
输出
12 [(1, 0), (0, 0)]
极限计算可以写成
lim = 0.68 * total
但是如果您的数据保证是整数,那么将 lim
也作为整数会更整洁,因为比较 2 个整数比比较整数和 float 稍微更有效。当您执行结合 int 和 float 的操作(包括比较)时,必须将它们转换为通用类型才能执行操作。
这是一个替代版本,如评论中所讨论的那样。它循环遍历 vals
中的值,直到达到所需的总和,同时跟踪 vals
中的索引。然后它使用该索引将使用的值和相应的坐标元组从 b
列表切入新的 selected
列表(这与 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)
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
关于Python - 选择总和为 2D 列表中累积总和的 68% 的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40359938/