我正在查看坐标数据,由于某些预处理,我看到一些参数不同的重复坐标。我希望能够合并与匹配坐标对应的属性并获得简化的结果。为了阐明我的意思,这是一个示例:
X = [1.0, 2.0, 3.0, 2.0]
Y = [8.0, 3.0, 4.0, 3.0]
A = [13, 16, 20, 8]
以上数据的读取方式如下:点(1.0,8.0)的值为13,而(2.0,3.0)的值为16。请注意,第二点和第四点的坐标相同,但属性值不同。我希望能够从坐标列表中删除重复项并求和属性,以便结果成为新列表:
New_X = [1.0, 2.0, 3.0]
New_Y = [8.0, 3.0, 4.0]
New_A = [13, 24, 20]
24是具有相同坐标的第二和第四点的16和8的和,因此保留一个点并对其求和。
我不确定如何执行此操作,我曾考虑过使用嵌套的for for循环的坐标zips,但不确定如何将其公式化以求和。
感谢您的帮助!
答案 0 :(得分:4)
我认为维护3个列表有点尴尬。像这样:
D = dict()
for x,y,a in zip(X,Y,A):
D[(x,y)] = D.get((x,y),0) + a
将所有内容放在一起。
如果您希望将其分解为3个列表:
for (x,y),a in D.items():
newX.append(x)
newY.append(y)
newA.append(a)
答案 1 :(得分:2)
这里的另一个选项是使用itertools.groupby
。但是,由于这只会对连续的键进行分组,因此您必须首先对坐标进行排序。
首先,我们可以将它们zip
一起创建(x, y, a)
形式的元组。然后按(x, y)
坐标对它们进行排序:
sc = sorted(zip(X, Y, A), key=lambda P: (P[0], P[1])) # sorted coordinates
print(sc)
#[(1.0, 8.0, 13), (2.0, 3.0, 16), (2.0, 3.0, 8), (3.0, 4.0, 20)]
现在我们可以groupby
坐标并求和:
from itertools import groupby
print([(*a, sum(c[2] for c in b)) for a, b in groupby(sc, key=lambda P: (P[0], P[1]))])
#[(1.0, 8.0, 13), (2.0, 3.0, 24), (3.0, 4.0, 20)]
自zip
is its own inverse起,您可以通过以下方式获取New_X
,New_Y
和New_A
:
New_X, New_Y, New_A = zip(
*((*a, sum(c[2] for c in b)) for a, b in groupby(sc, key=lambda P: (P[0], P[1])))
)
print(New_X)
print(New_Y)
print(New_A)
#(1.0, 2.0, 3.0)
#(8.0, 3.0, 4.0)
#(13, 24, 20)
当然,您可以在一行中完成所有操作,但是我将其分解成几部分,以便于理解。
答案 2 :(得分:1)
您可以将(x,y)
坐标放入字典中:
dict = {}
for i in range(len(X)) # len(X) = len(Y)
if (X[i], Y[i]) not in dict.keys():
dict[(X[i], Y[i])] = A[i]
else:
dict[(X[i], Y[i])] += A[i]
答案 3 :(得分:1)
可以使用字典
d = {}
for i in range(len(X)):
tup = (X[i], Y[i])
if tup in d:
d[tup] += A[i]
else:
d[tup] = A[i]
New_X = []
New_Y = []
New_A = []
for key in d.keys():
New_X.append(key[0])
New_Y.append(key[1])
New_A.append(d[key])
答案 4 :(得分:1)
尝试此列表理解:
y,x,a=zip(*[e for c,e in enumerate(zip(Y,X,A)) if not e[0:1] in [x[0:1] for x in zip(X,Y,A)][c:]])
答案 5 :(得分:1)
在这里dict
似乎更合适。这将建立一个。
from collections import Counter
D = sum((Counter({(x, y): a}) for x, y, a in zip(X, Y, A)), Counter())
print(D)
#Counter({(2.0, 3.0): 24, (3.0, 4.0): 20, (1.0, 8.0): 13})
您可以使用以下命令将这些文件重新打包成单独的列表:
New_X, New_Y, New_A = map(list, zip(*[(x,y,a) for (x,y),a in D.items()]))
print(New_X)
print(New_Y)
print(New_A)
#[1.0, 2.0, 3.0]
#[8.0, 3.0, 4.0]
#[13, 24, 20]