这是Mathematica中另一个简单的“矩阵”问题。我想说明我是如何做到的,并询问是否有更好的答案。
我想根据第一列中的值(或任何列,我在这里使用第一列作为示例)从矩阵中选择所有'行'。
比如说,在这个例子中找到第一个位置的条目< = 4的所有行:
list = {{1, 2, 3},
{4, 5, 8},
{7 , 8, 9}}
所以,结果应该是
{{1,2,3},
{4,5,8}}
嗯,问题是我需要使用Position,因为Position返回的结果可以直接由Extract使用。 (但不能被Part或[[]]使用,所以这就是为什么我只是看着Position [])。
但我不知道怎么告诉Position请将'搜索'模式限制为只有'第一列'所以我可以在一行中完成。
当我输入
pos = Position[list, _?(# <= 4 &)]
返回&lt; = 4的所有条目的位置。
{{1, 1}, {1, 2}, {1, 3}, {2, 1}}
如果我第一次获得第一列,则在其上应用“位置”,它可以使用
list = {{1, 2, 3},
{4, 5, 8},
{7 , 8, 9}};
pos = Position[list[[All, 1]], _?(# <= 4 &)]
Extract[list, pos]
--> {{1, 2, 3}, {4, 5, 8}}
我也尝试过这个:
pos = Position[list, _?(# <= 4 &)];
pos = Select[pos, #[[2]] == 1 &] (*only look at ones in the 'first' column*)
{{1, 1}, {2, 1}}--->
这给了我第一栏中的正确位置。要使用它来查找所有行,我做了
pos = pos[[All, 1]] (* to get list of row positions*)
---> {1, 2}
list[[ pos[[1]] ;; pos[[-1]], All]]
{{1, 2, 3},
{4, 5, 8}}
所以,要总结,把它们放在一起,这就是我所做的:
list = {{1, 2, 3},
{4, 5, 8},
{7 , 8, 9}};
pos = Position[list[[All, 1]], _?(# <= 4 &)]
Extract[list, pos]
--> {{1, 2, 3}, {4, 5, 8}}
list = {{1, 2, 3},
{4, 5, 8},
{7 , 8, 9}}
pos = Position[list, _?(# <= 4 &)];
pos = Select[pos, #[[2]] == 1 &];
pos = pos[[All, 1]];
list[[ pos[[1]] ;; pos[[-1]], All]]
{{1, 2, 3},
{4, 5, 8}}
The above clearly is not too good.
方法1是否采用“正确”的功能方式?
作为参考,这就是我在Matlab中执行上述操作的方法:
EDU>> A=[1 2 3;4 5 8;7 8 9]
A =
1 2 3
4 5 8
7 8 9
EDU>> A( A(:,1)<=4 , :)
1 2 3
4 5 8
我正在尝试改进我在Mathematica命令中使用矩阵的“功能”处理,这是一个我觉得我不擅长使用列表的领域。我发现使用矩阵更容易。
问题是:Mathematica中是否有更短/更实用的方法?
感谢
答案 0 :(得分:7)
您可以按如下方式使用Pick[]:
Pick[list, list[[All, 1]], _?(# <= 4 &)]
答案 1 :(得分:5)
以下情况如何?
In[1]:= list = {{1, 2, 3}, {4, 5, 8}, {7, 8, 9}};
In[2]:= Select[list, First[#] <= 4 &]
Out[2]= {{1, 2, 3}, {4, 5, 8}}
这是matlab代码的简单翻译:
list[[Flatten[Position[Thread[list[[All, 1]] <= 4], True]]]]
(当然,如果我使用Flatten
代替Extract
),则不需要Part
。
答案 2 :(得分:4)
使用SparseArray
的方法比已经提出的方法更快。它是:
list ~Extract~
SparseArray[UnitStep[4 - list[[All, 1]]]]["NonzeroPositions"]
以下是与其他方法的速度比较。我不得不修改WReach的方法来处理其他位置规范。
f1[list_, x_] := Cases[list, {Sequence @@ Table[_, {x - 1}], n_, ___} /; n <= 4]
f2[list_, x_] := Select[list, #[[x]] <= 4 &]
f3[list_, x_] := Pick[list, (#[[x]] <= 4 &) /@ list]
f4[list_, x_] := Pick[list, UnitStep[4 - list[[All, x]]], 1]
f5[list_, x_] := Pick[list, Thread[list[[All, x]] <= 4]]
f6[list_, x_] := list ~Extract~
SparseArray[UnitStep[4 - list[[All, x]]]]["NonzeroPositions"]
对于包含少量行和多列的表(比较位置7):
a = RandomInteger[99, {250, 150000}];
timeAvg[#[a, 7]] & /@ {f1, f2, f3, f4, f5, f6} // Column
0.02248 0.0262 0.312 0.312 0.2808 0.0009728
对于列数较少且行数较多的表(比较位置7):
a = RandomInteger[99, {150000, 12}];
timeAvg[#[a, 7]] & /@ {f1, f2, f3, f4, f5, f6} // Column
0.0968 0.1434 0.184 0.0474 0.103 0.002872
答案 3 :(得分:3)
如果您想要符合条件的行,请使用Cases
:
Cases[list, {n_, __} /; n <= 4]
(* {{1, 2, 3}, {4, 5, 8}} *)
如果您想要列表中的位置而不是行本身,请使用Position
代替Cases
(仅限于第一级):
Position[list, {n_, __} /; n <= 4, {1}]
(* {{1}, {2}} *)
答案 4 :(得分:2)
如果你想变得非常聪明:
Pick[list, UnitStep[4 - list[[All, 1]]], 1]
这也避免了解压缩,这意味着它会更快并且使用更少的内存。