开发者

Conditional list values replacement in Mathematica

Please consider :

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}}

Conditional list values replacement in Mathematica

COGCondition1 = 10
COGCondition2 = 20

I would like to replace the values in column "Blah" given the value taken in column "COGCondition" such that:

If, for a given row, the value in column "COGCondition" = 1 the value in column "Blah" should be equal to COGCondition1 (And 2 -> COGCondition2)

Desired output:

Conditional list values replacement in Mathematica

I need this for a large data set and my attempts using Table and Switch have failed. I can easily generate new columns but can't figure out how to replace values using Switch.


This is fairly straightforward with a replacement rule:

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

gives

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

Alternatively, you could use MapThread

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

which returns

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

Edit: In your updated version of dalist, you have four columns: noise, data, noise, and condition. The update to the pattern version is simply

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

Unfortunately, this is somewhat fragile because it requires a bit of extra work if you change the number of conditions. The method suggested by Leonid, was to create a function

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

then this simplifies the update code

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

Alternatively, you could create a list of rules

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

then the code for changing dalist becomes

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

If you find that you have more than 1 column between x and y, then your pattern is simply {a_, x_, b___, y_Integer}. Or, if the number of columns prior to x is larger than one, use {a___, x_, b_, y_Integer}. However, they don't work together because Mathematica needs to know where x and y are relative to some point in the list, or it won't operate as you expect, if at all.

But, if you know the number of columns, you can use PatternSequence. For example, if you have 3 columns of noise, your data, 5 columns of noise, and then you condition, your replacement rule would be

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

Now, PatternSequence@@Array[_&,3] could be written PatternSequence[_, _, _], but by using Array it gives more flexibility.


Edit: One difficulty with either the indexed variable form, COGCondition[n], or the rule form is if the condition column contains values other than 1 or 2. The simplest solution is to set up a default value, e.g.

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

or add to conditions

_ :> default

One possibility is to emit a Message whenever this default is encountered which would provide feed back as its running.

Another possibility is to have the data column remain untouched if the default is encountered. To accomplish this, we can use the following

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

which would be used like

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

To make this work with the rule implementation, we make conditions a function which accepts the current data value

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

which changes the code for updating dalist to

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

Note, either of the last two methods can be combined with emitting a Message from above.


I would use:

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

dalist //TableForm

Conditional list values replacement in Mathematica

If modification of dalist is undesired, you can copy it first, e.g. dalist2 = dalist and then modify the copy.

Especially if you have many values for the condition column, I suggest you follow the earlier recommendation to use an indexed variable (COGCondition[1]). This would look like:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜