Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have the following data set:

data = {{"Jakarta","Surabaya","Bandung"},{1,2,3}}

and I'd actually like to assign the numerical values to the categorical data so that Jakarta = 1, Surabaya = 2 and Bandung = 3.

If I use MapThread[Set, {ToExpression[data[[1]]], data[[2]]}]it works fine but when I try to assign the variables individually I keep on getting error messages:

ToExpression[data[[1, 1]]] = data[[2, 1]]
Set::write: "Tag ToExpression in ToExpression[Jakarta] is Protected."

However, ToExpression[data[[1,1]] works fine

May I know why my second approach is not working?

share|improve this question

3 Answers 3

up vote 8 down vote accepted

I believe it is because Set has attribute HoldFirst. The FullForm of what you are attempting would look like...

Set[ToExpression[data[[1,1]]],1]

The ToExpression doesn't get a chance to evaluate before trying to assign the value. You can use Evaluate if you insist on doing it this way.

Evaluate[ToExpression[data[[1, 1]]]] = data[[2, 1]]
share|improve this answer
    
Thank you for the clarification. I understand the reason now. –  Ruben.Garcia Mar 22 '12 at 9:40

Since Set attempts to assign to the object on the LHS itself, unless that object has head List, you are attempting to assign a value to ToExpression[data[[1, 1]]] just as the error message informs you.

Also, you will have a problem if your symbol names already have a value when you try your MapThread method. You need a way to get and hold the unevaluated symbol and then pass it to Set. This can be done with ToHeldExpression (or MakeExpression) as follows:

MapThread[
 Set @@ Append[ToHeldExpression@#, #2] &,
 data
]

This works by building the arguments for Set inside Hold and then passing them to Set with Apply (@@).

Doing this for a single element:

Set @@ Append[ToHeldExpression[ data[[1, 1]] ], data[[2, 1]] ]
share|improve this answer
    
Thank you for the explanations. I didn't know there was such a command (ToHeldExpression) –  Ruben.Garcia Mar 22 '12 at 9:42

I think avoiding ToExpression is important, so here is a solution using Symbol:

MapThread[With[{var = (Clear[#1]; Symbol[#1])}, var = #2] &, data]

I use Clear to be sure that the symbol has not a previous value defined, which would generate an assigment error.

You can also use Evaluate instead With as @Andy answer:

MapThread[(Clear[#1]; Evaluate[Symbol[#1]] = #2) &, data]
share|improve this answer
    
Thanks a lot for the suggestion. I implemented it in my code and it works perfectly. –  Ruben.Garcia Mar 22 '12 at 9:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.