我想逐个元素地比较矩阵并找到矩阵的最大值,就像我有三个3x3矩阵一样
tdata = {{{1, 5, 1}, {7, 4, 2}, {2, 4, 3}}, {{2, 0, 8}, {9, 8, 2}, {2,
3, 0}}, {{2, 2, 9}, {10, 9, 5}, {9, 3, 3}}}
然后使用
MapThread[Max, tdata, 2] // MatrixForm
我可以得到正确的结果。
{{2, 5, 9}, {10, 9, 5}, {9, 4, 3}}
但是,当矩阵是复杂矩阵时,Max函数不起作用。例如,
tdata = {{{0.323031 + 5.23687 I, 8.92856 + 1.31365 I},
{9.94387 + 3.04104 I, 8.72483 + 2.5648 I}},
{{5.96575 + 9.2521 I, 8.58461 + 2.56753 I},
{0.902715 + 3.75791 I, 4.06809 + 8.61552 I}},
{{9.36592 + 1.17263 I, 9.74628 + 2.22183 I},
{4.61866 + 4.61158 I, 9.0791 + 2.50036 I}}}
我试图为复杂矩阵实现一个新的Max函数,但它不起作用。这是一个演示,
complexMax[lis_] := Module[{abs = Abs[lis]}, Take[lis, Position[abs, Max[abs]][[1]]]]
然后
MapThread[complexMax, tdata, 2]
结果就像
{{complexMax[0.323031 + 5.23687 I, 5.96575 + 9.2521 I, 9.36592 + 1.17263 I],
complexMax[8.92856 + 1.31365 I, 8.58461 + 2.56753 I, 9.74628 + 2.22183 I]},
{complexMax[9.94387 + 3.04104 I, 0.902715 + 3.75791 I, 4.61866 + 4.61158 I],
complexMax[8.72483 + 2.5648 I, 4.06809 + 8.61552 I, 9.0791 + 2.50036 I]}}
有任何想法如何解决问题?
答案 0 :(得分:2)
我认为这就是你想要的:
MapThread[Last@SortBy[{##}, Abs] &, tdata, 2] // MatrixForm
(* {{5.96575 + 9.2521 I,9.74628 + 2.22183 I},{9.94387 + 3.04104 I, 4.06809 + 8.61552 I}} *)
FWIW按规范排序复杂的数字,(实部首先)
MapThread[Last@Sort[{##}] &, tdata, 2] // MatrixForm
(* {{9.36592 + 1.17263 I,9.74628 + 2.22183 I},{9.94387 + 3.04104 I, 9.0791 + 2.50036 I}} *)
请注意,如果您执行此操作,您的方法也会起作用:
MapThread[complexMax[{##}] &, tdata, 2]
诀窍是Mapthread
传递给你的函数的参数是一个序列,而不是一个列表。
答案 1 :(得分:2)
当前代码的问题在于使用MapThread
会导致complexMax
被调用而不是单个参数是一个列表(即complexMax[{elem1, elem2, elem3...}]
),但是有多个参数(即complexMax[elem1, elem2, elem3]
)。
您可以通过将参数声明为单个表达式(lis_
w / single下划线)但作为表达式序列来解决此问题:lis__
带有双下划线。
进行此更正会导致另一个问题,但Abs
需要列表作为输入,Take
也是如此。因此,您需要将lis
括在括号中的几个地方。
最后,看起来你最后还需要一个[[1]]
。
complexMax[lis__] := Module[{abs = Abs[{lis}]},
Take[{lis}, Position[abs, Max[abs]][[1]]][[1]]]
MapThread[complexMax, tdata, 2]
结果
{{5.96575 + 9.2521 I, 9.74628 + 2.22183 I}, {9.94387 + 3.04104 I,
4.06809 + 8.61552 I}}
答案 2 :(得分:1)
现在有一个专门用于 Mathematica 的StackExchange网站:https://mathematica.stackexchange.com/ - 请在那里询问您未来的问题。
正如latkin已经解释的那样,如果要使用MapThread
中所示的最大函数,则需要接受多个参数。您可以使用第二种模式编写函数来处理两种形式,例如: cMax[ns__] := cMax[{ns}]
。
比Position
更快Ordering
。
cMax[ns__] := cMax[{ns}]
cMax[lis_List] := lis ~Extract~ Ordering[Abs[lis], -1]
现在:
MapThread[cMax, tdata, 2]
{{5.96575 + 9.2521 I, 9.74628 + 2.22183 I}, {9.94387 + 3.04104 I, 4.06809 + 8.61552 I}}
但是,使用打包数据时,使用MapThread
会更快 ,从而导致解包,而是使用Transpose
将数字保留在列表中:
Map[cMax, Transpose[tdata, {3, 1, 2}], {2}]
{{5.96575 + 9.2521 I, 9.74628 + 2.22183 I}, {9.94387 + 3.04104 I, 4.06809 + 8.61552 I}}
时序:
cd = RandomComplex[9 + 9 I, {15000, 7, 7}];
MapThread[Last@SortBy[{##}, Abs] &, cd, 2] // Timing // First
MapThread[cMax, cd, 2] // Timing // First
Map[cMax, Transpose[cd, {3, 1, 2}], {2}] // Timing // First
0.562
0.483
0.0156