I have a dataframe df:
colour shape
'red' circle
'blue' square
'blue' circle
'green' sphere
And a double matrix m with named rows/columns
circle square sphere
red 1 4 7
blue 2 5 8
green 3 6 9
I'd like to add a new column to DF such that I obtain:
id colour shape
1 'red' circle
5 'blue' square
2 'blue' circle
9 'green' sphere
I've tried doing this with the following code but it doesn't seem to work:
df$id <- m[df$colour,df$shape]
I've also tried apply(); and similar but with no luck. Can anyone tell me the right approach to doing this without using a loop?
You could also convert the matrix m to a vector and then match the ID to the colour and shape values:
The next step matches the colour in df to the appropriate dimname in the m matrix, then adds an integer corresponding to the shape. The result in the index of the m vector with the corresponding ID.
Another answer Using the reshape2 and plyr (optional just for join) packages.
Hope this help
I think I might win the shortest answer contest here as long as those are character vectors rather than factors which might be more expected unless you made specifid effort to avoid. It really only adds
cbind
to convert the two df "character" vectors to a two column matrix expected by the[.matrix
function that you were very close to success in using. (And it also seems reasonably expressive.)A rather simple (and fast!) alternative is to use a matrix to index into your matrix:
The
match
function is used to find the corresponding numeric index for a particular string.Note that in newer version of R (2.13 and newer I think), you can use character strings in the index matrix. Unfortunately, the color and shape columns are typically
factors
, andcbind
doesn't like that (it uses the integer codes), so you need to coerce them withas.character
:...I suspect that using
match
is more efficient though.EDIT I measured and it seems to be about 20% faster to use
match
:merge()
is your friend here. To use it, we need an appropriate data frame to merge with containing the stacked version of your ID matrix. I create that asnewdf
with the code below:Which results in:
Then with your original data in object
df2
, defined usinguse
merge()
You can store that and rearrange the columns if you need that: