请考虑:
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}}
COGCondition1 = 10
COGCondition2 = 20
我想替换“Blah”列中的值,给出“COGCondition”列中的值,使得:
如果对于给定的行,“COGCondition”列中的值= 1,则“Blah”列中的值应等于COGCondition1(和2 - > COGCondition2)
期望的输出:
我需要这个用于大型数据集,而我使用Table
和Switch
的尝试失败了。我可以轻松生成新列,但无法弄清楚如何使用Switch
替换值。
答案 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}
如果您发现x
和y
之间的列数超过1列,则您的模式只是{a_, x_, b___, y_Integer}
。或者,如果x
之前的列数大于1,请使用{a___, x_, b_, y_Integer}
。但是,它们不能一起工作,因为Mathematica需要知道x
和y
相对于列表中的某个点的位置,或者它将无法按预期运行(如果有的话)。
但是,如果您知道列数,则可以使用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
如果不希望修改dalist
,您可以先复制它,例如dalist2 = dalist
然后修改副本。
特别是如果条件列有很多值,我建议您按照之前的建议使用索引变量(COGCondition[1]
)。这看起来像是:
dalist[[2 ;;, 2]] = COGCondition /@ dalist[[2 ;;, 4]];