Message Boards Message Boards

1
|
7011 Views
|
4 Replies
|
1 Total Likes
View groups...
Share
Share this post:

Generalize this function for ratio of a list element?

Posted 6 years ago

How do I generalize this function so it can take any matrix and, for each row, take the ratio of each element to the n'th element of that row? Mapping works if I want to use the default position I set, but not if I want to specify a position.

Function:

rationormalize4[list_, pos_ : 4] := list/list[[pos]]

Here's what works and what doesn't... Apply to a list with the default position of 4 - works:

In[76]:= rationormalize4[{1, 4, 2, 6}]

Out[76]= {1/6, 2/3, 1/3, 1}

Map over a matrix a.k.a. list of lists with the default position of 4 - works:

In[78]:= Map[rationormalize4, {{1, 3, 1, 6}, {2, 5, 7, 9}}]

Out[78]= {{1/6, 1/2, 1/6, 1}, {2/9, 5/9, 7/9, 1}}

Apply to a list of lists with a non-default position - doesn't work, thinks pos_ is the second list instead of the second element. Is there a way to write in a level specification?:

In[80]:= rationormalize4[{{1, 3, 1, 6}, {2, 5, 7, 9}}, 2]

During evaluation of In[80]:= Thread::tdlen: Objects of unequal length in {{1,3,1,6},{2,5,7,9}} {1/2,1/5,1/7,1/9} cannot be combined.

Out[80]= {{1, 3, 1, 6}, {2, 5, 7, 9}} {1/2, 1/5, 1/7, 1/9}

Setting attributes to Listable - doesn't work because then the function thinks it has to take the second element of each element and gets confused:

In[81]:= SetAttributes[rationormalize4, Listable]

In[82]:= rationormalize4[{{1, 3, 1, 6}, {2, 5, 7, 9}}, 2]

During evaluation of In[82]:= Part::partd: Part specification 1[[2]] is longer than depth of object.

During evaluation of In[82]:= Part::partd: Part specification 3[[2]] is longer than depth of object.

During evaluation of In[82]:= Part::partd: Part specification 1[[2]] is longer than depth of object.

During evaluation of In[82]:= General::stop: Further output of Part::partd will be suppressed during this calculation.

Out[82]= {{1/1[[2]], 3/3[[2]], 1/1[[2]], 6/6[[2]]}, {2/2[[2]], 5/
  5[[2]], 7/7[[2]], 9/9[[2]]}}

Any help is appreciated - I'm making a bunch of data analysis functions for chemistry.

4 Replies

this is also a solution

rationormalize4[list_?VectorQ, pos_Integer: 4] := list/list[[pos]]
rationormalize4[list_?ListQ, pos_Integer: 4] := rationormalize4[#, pos] & /@ list

Maybe not as compact but will not give errors for non list inputs

In[4]:= rationormalize4[{{1, 2, 4, 6, 7}, "a", 1}, 2]

Out[4]= {{1/2, 1, 2, 3, 7/2}, rationormalize4["a", 2], rationormalize4[1, 2]}

In[5]:= rationormalize4[{{1, 2, 4, 6, 7}, "a", 1}, 2.2]

Out[5]= rationormalize4[{{1, 2, 4, 6, 7}, "a", 1}, 2.2]

An it can handle uneven dephts

In[6]:= rationormalize4[{{1, 3, 1, 6}, {{1, 3, 1, 6}, {2, 5, 7, 9}}}, 2]

Out[6]= {{1/3, 1, 1/3, 2}, {{1/3, 1, 1/3, 2}, {2/5, 1, 7/5, 9/5}}}

In[8]:= ratioNormalize5[{{1, 3, 1, 6}, {{1, 3, 1, 6}, {2, 5, 7, 9}}}, 2]

During evaluation of In[8]:= Thread::tdlen: Objects of unequal length in {{1/3,1,1/3,2},{2/5,1,7/5,9/5}} {5/2,1,5/7,5/9} cannot be combined.

Out[8]= {{1/3, 1, 1/3, 2}, {{1/3, 1, 1/3, 2}, {2/5, 1, 7/5, 9/5}} {5/2, 1, 5/7, 5/9}}
POSTED BY: Martijn Froeling

Update: I think this version of the function from dan Erickson is working:

ratioNormalize5[list_, pos_ : 4] := Map[(#/#[[pos]]) &, list, -2]

Try this formulation:

ratioNormalize[list, pos_ 4] := Map[(#/#[[pos]]) &, list, -2]
POSTED BY: dan Erickson

you could just map all the time? it is not very elegant but a typical mma programming thing to do hehe. and this also saves you the efforts to add further DownValues which could lead to new problems. "The less DownValues the better." That's the golden rule of programming.

data = {{1, 3, 1, 6}, {2, 5, 7, 9}};
rationormalize4[#, 2] & /@ data

and if you're like me, then the second golden rule of programming is to avoid using code which is confusing or hard to understand now. If you have difficulties understanding the code now, you will have the same difficulties then in future again, when you revisit the code (for revision, maintenance, sharing, whatever) because we humans tend to forget complicated things we once understood and only remember well the few things which were clear, short, and simple.

if you have a choice, then the simplest solution is the preferable solution. rock solid, robust, straight-forward, and you have full confidence in employing it.

POSTED BY: Raspi Rascal
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract