是否有一个简单的解决方案用两个NumPy
子阵列替换单个子阵列,而entires是在两个前阵列的条目上调用函数的结果。
例如:
[1, a, b][1, c, d] -> [1, f_add, f_sub]
使用:
f_add(a, b, c, d):
return a + b + c + d
f_sub(b, d):
return b-d
具体:
[1, 0, 50], [1, 3, 1] -> [1, 54, 49]
作为补充,行[1, 0, 50], [1, 3, 1]
是更大数组的一部分(示例中为第一行),因此应该就地替换
([[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]],
[[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]])
([[1, 54, 49], [2, 0, 50]],
[[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]])
谢谢!
修改
函数f_add
和f_sub
只是示例,用于说明我想要做什么,以及条目的更改是调用函数的结果。
实际上,我使用稍微复杂的函数来执行(更有意义的)计算。
第二件事是,这种替换只应在第一个条目相同的元素上进行。
因此,在第一行中只有[1, 0. 50.]
和[1, 3.0, 1.0]
合并,而在第二行中,它将是[2, 0., 50.]
和[2, 30, 1.0)
。
在这个例子中,我首先想要通过比较索引来分离确定哪些子数组要合并的问题,但我想它应该尽可能地包括在内。
上面的一个更完整的示例结果如下:
([[1, 0., 50.], [2, 0., 50], [1, 3.0, 1.0]],
[[1, 0., 50.], [2, 0., 50.], [2, 3.0, 1.0]])
导致:
([[1, 54., 49.], [2, 0., 50.]],
[[1, 0., 50.], [2, 54., 49.]])
答案 0 :(得分:0)
您可以使用生成器表达式来获得此结果(假设数组的每个元素有三个子元素):
ar = ([[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]],
[[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]])
ar = tuple([[[x[0][0], sum(x[0][1:]) + sum(x[-1][1:]), x[0][-1]-x[-1][-1]], x[1]] for x in ar])
print ar
([[1,54.0,49.0],[2,0,50]],[[1,54.0,49.0],[2,0,50]]
编辑:也许对于更通用的解决方案,您可以定义一个函数f(x)
,它对数组的元素执行所需的计算,并将该函数映射到数组的每一行。例如,
def f(x):
if (x[0][0] == x[1][0]):
return [[x[0][0], x[0][1]+x[0][2]+x[1][1]+x[1][2], x[0][2]-x[1][2]], x[2]]
elif (x[0][0] == x[2][0]):
return [[x[0][0], x[0][1]+x[0][2]+x[2][1]+x[2][2], x[0][2]-x[2][2]], x[1]]
elif (x[1][0] == x[2][0]):
return [x[0], [x[1][0], x[1][1]+x[1][2]+x[2][1]+x[2][2], x[1][2]-x[2][2]]]
else:
return x
ar = ([[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]],
[[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]])
print tuple(map(f, ar))
([[1,54.0,49.0],[2,0,00]],[[1,0,50],[2,54.0,49.0]]
答案 1 :(得分:0)
如果你有很多函数在数组上工作,听起来好像很复杂。我会考虑将每一行分成一个类来更简洁地管理函数调用。例如,您可以包含类中的所有相关函数:
class Row:
def __init__(self, row):
self.row = row
self.sum1 = None
self.sub1 = None
self._add(row)
self._sub(row)
def _add(self, items):
self.sum1 = sum([items[0][1], items[0][2], items[-1][1], items[-1][2]])
def _sub(self, items):
self.sub1 = items[0][2] - items[-1][2]
def update(self):
self.row = [[self.row[0][0], self.sum1, self.sub1], self.row[1]]
# Data
arr = ([[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]],
[[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]])
# Usage
for row in arr:
r = Row(row)
print r.sum1, r.sub1
r.update()
print r.row
>>> 54.0 49.0
[[1, 54.0, 49.0], [2, 0, 50]]
54.0 49.0
[[1, 54.0, 49.0], [2, 0, 50]] # This row doesnt match your example, but you get the idea
答案 2 :(得分:0)
这是执行第一个(最内部)步骤的函数,假设2个输入是列表:
def merge(a,b):
res = [a[0]] # test b[0] is same?
abcd = a[1:]+b[1:] # list join
# use np.concatenate here is a,b are arrays
res.append(f_add(*abcd))
res.append(f_sum(a[2],b[2]))
return res
def f_add(a,b,c,d):
return a+b+c+d
def f_sum(b,d):
return b-d
In [484]: merge([1,0,50],[1,3,1])
Out[484]: [1, 54, 49]
通过混合使用元素和一般函数,将这些作为数组处理没有多大意义。
然后编写一个函数来处理'row',列表中列出了具有相同x[0]
id的列表。收集匹配对的最简单方法(只有对吗?)是defaultdict
。
所以我找到了对;并将它们与上述功能合并。
def subs(alist):
# collect the matching ids
from collections import defaultdict
dd = defaultdict(list)
for i,x in enumerate(alist):
dd[x[0]].append(x)
# merge pairs
for i in dd.keys():
if len(dd[i])==2:
dd[i]=merge(dd[i][0],dd[i][1])
elif len(dd[i])==1:
dd[i]=dd[i][0] # flatten
else:
pass # do nothing with triplets etc.
return list(dd.values())
In [512]: lll= [[[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]],
...: [[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]]]
In [513]: [subs(l) for l in lll]
Out[513]: [[[1, 54.0, 49.0], [2, 0, 50]],
[[1, 0, 50], [2, 54.0, 49.0]]]
lll
可以变成3d数组:
In [523]: arr=np.array(lll)
In [524]: arr
Out[524]:
array([[[ 1., 0., 50.],
[ 2., 0., 50.],
[ 1., 3., 1.]],
[[ 1., 0., 50.],
[ 2., 0., 50.],
[ 2., 3., 1.]]])
我们要混合和匹配的ID是:
In [525]: arr[:,:,0]
Out[525]:
array([[ 1., 2., 1.],
[ 1., 2., 2.]])
要合并的对是
In [526]: arr[0,[0,2],:]
Out[526]:
array([[ 1., 0., 50.],
[ 1., 3., 1.]])
和2次合并:
In [527]: merge(*arr[0,[0,2],:].tolist())
Out[527]: [1.0, 54.0, 49.0]
In [528]: merge(*arr[1,[1,2],:].tolist())
Out[528]: [2.0, 54.0, 49.0]
但是,识别这些对,并执行合并并构建新数组并不比使用列表更容易。
In [532]: np.array([subs(l.tolist()) for l in arr])
Out[532]:
array([[[ 1., 54., 49.],
[ 2., 0., 50.]],
[[ 1., 0., 50.],
[ 2., 54., 49.]]])