Mathematica中的条件列表值替换

时间:2011-08-16 13:53:32

标签: replace wolfram-mathematica conditional

请考虑:

dalist = Transpose@{{"Noise1",1,1,1,1,1},{"Blah", 1, 2, 3, 4, 5},
                   {"Noise2",2,2,2,2,2}, {"COGCondition", 1, 2, 1, 2, 1}}

enter image description here

COGCondition1 = 10
COGCondition2 = 20

我想替换“Blah”列中的值,给出“COGCondition”列中的值,使得:

如果对于给定的行,“COGCondition”列中的值= 1,则“Blah”列中的值应等于COGCondition1(和2 - > COGCondition2)

期望的输出:

enter image description here

我需要这个用于大型数据集,而我使用TableSwitch的尝试失败了。我可以轻松生成新列,但无法弄清楚如何使用Switch替换值。

2 个答案:

答案 0 :(得分:7)

对于替换规则,这是相当简单的:

dalist /.
  {x_?NumericQ, y_?NumericQ} :> 
  {Which[y==1, COGCondition1, y==2, COGCondition2], y}

给出

{{"Blah", "COGCondition"}, {10, 1}, {20, 2}, {10, 1}, {20, 2}, {10, 1}}.

或者,您可以使用MapThread

MapThread[ 
    If[ !NumericQ[#2], #1,
      Which[#2==1, COGCondition1, #2==2, COGCondition2] ]&,
   Transpose@dalist]

返回

{"Blah", 10, 20, 10, 20, 10}.

修改:在dalist的更新版本中,您有四列:噪音,数据,噪音和条件。模式版本的更新只是

dalist /.
  {a_, x_, b_, y_} :> 
  {a, Which[y==1, COGCondition1, y==2, COGCondition2], b, y}

不幸的是,这有点脆弱,因为如果你改变条件的数量,它需要一些额外的工作。 Leonid建议的方法是创建一个函数

Clear[COGCondition]
COGCondition[1] = 10
COGCondition[2] = 20

然后这简化了更新代码

dalist /.
  {a_, x_, b_, y_Integer} :> {a, COGCondition[y], b, y}

或者,您可以创建规则列表

conditions = { 1 -> 10, 2 -> 20 }

然后更改dalist的代码变为

dalist /.
  {a_, x_, b_, y_Integer} :> {a, y /. conditions, b, y}

如果您发现xy之间的列数超过1列,则您的模式只是{a_, x_, b___, y_Integer}。或者,如果x之前的列数大于1,请使用{a___, x_, b_, y_Integer}。但是,它们不能一起工作,因为Mathematica需要知道xy相对于列表中的某个点的位置,或者它将无法按预期运行(如果有的话)。

但是,如果您知道列数,则可以使用PatternSequence。例如,如果你有3列噪音,你的数据,5列噪音,然后你有条件,你的替换规则将是

dalist /.
  {a:PatternSequence@@Array[_&,3], x_, 
   b:PatternSequence@@Array[_&,5], y_Integer} :> {a, y /. conditions, b, y}

现在,PatternSequence@@Array[_&,3]可以写为PatternSequence[_, _, _],但使用Array可以提供更大的灵活性。


编辑:索引变量形式COGCondition[n]或规则形式的一个难点是条件列包含的值不是1或2.最简单的解决方案是设置一个默认值,例如

COGCondition[_] := default (*where default may be defined elsewhere *)

或添加到conditions

_ :> default

一种可能性是在遇到此默认值时发出Message,这会在运行时提供反馈。

另一种可能性是,如果遇到默认值,则数据列保持不变。为此,我们可以使用以下

COGCondition[1,_] := 10
(*define the rest of the known values as above*)
COGCondition[_,d_]:= default (*encountered only if the 1st var is unknown*)

将像

一样使用
dalist /.
  {a_, x_, b_, y_Integer} :> {a, COGCondition[y, x], b, y}.

为了使这项工作与规则实现一致,我们使conditions成为一个接受当前数据值的函数

conditions[dat_] := { 1 -> 10, 2 -> 20, _ :> dat }

将更新dalist的代码更改为

dalist /.
  {a_, x_, b_, y_Integer} :> {a, y /. conditions[x], b, y}.

注意,最后两种方法中的任何一种都可以与从上面发出Message组合在一起。

答案 1 :(得分:6)

我会用:

dalist[[2 ;;, 2]] =
 dalist[[2 ;;, 4]] /. {1 -> COGCondition1, 2 -> COGCondition2};

dalist //TableForm

enter image description here

如果不希望修改dalist,您可以先复制它,例如dalist2 = dalist然后修改副本。

特别是如果条件列有很多值,我建议您按照之前的建议使用索引变量(COGCondition[1])。这看起来像是:

dalist[[2 ;;, 2]] = COGCondition /@ dalist[[2 ;;, 4]];