Re: Using Select with arrays? (Relative newbie)
- To: mathgroup at smc.vnet.net
- Subject: [mg54245] Re: Using Select with arrays? (Relative newbie)
- From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
- Date: Mon, 14 Feb 2005 21:50:37 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
>-----Original Message----- >From: Hugo Mallinson [mailto:hfm21 at cam.ac.uk] To: mathgroup at smc.vnet.net >Sent: Monday, February 14, 2005 4:17 AM >To: mathgroup at smc.vnet.net >Subject: [mg54245] Using Select with arrays? (Relative newbie) > >The subject might not be entirely correct, but here is my problem: > >I have a list of 5-variable data points like > >data = { >{1, 1, string1, c, d} >{1, 2, string2, c, d} >{1, 3, string3, c, d} >{1, 4, string4, c, d} >{2, 1, string1, c, d} >{2, 2, string2, c, d} >{3, 1, string3, c, d} >{4, 1, string2, c, d} >{4, 2, string4, c, d} >} > > >and I want to extract just the points that have 1 (or 2, etc) as their >first value. I think I should do something like > >Select[data, {1, _Integer, _String, _Integer, _Integer}] > >but that doesn't work. > >Having done that I need to find the maximum value of #2 for each >string, which I presumably do by the same method as above to extract >all string1 (or ...2) and then use Map[] and Max[]. I would do >this all >with For loops (revealing my lack of Mathematica chops :-) ) but I'd >really like to learn how to do this sort of extraction in a >Mathematica-y way. Any help would be greatly appreciated! > >Hugo > > Hugo, first check Length[data], if comes out as 1, then you had forgotten the comma separators for the elements of your outer list. If you want to select certain elements (say cases) of your list, the right command is Cases, not Select (check out with Help). And, I recommend, don't be overly specific with a pattern if you need not. So, as long as the symbols c, d haven't got integer values, your's won't match. (And I don't recommend to substitute _Symbol for _Integer here, then the pattern will not match if they _did_ get values.) This is fine: In[4]:= Cases[data, {1, __}] Out[4]= {{1, 1, "string1", c, d}, {1, 2, "string2", c, d}, {1, 3, "string3", c, d}, {1, 4, "string4", c, d}} For your second question, I propose (there are dozens of different solutions) In[5]:= (# -> Max[Cases[data, {_, x_, #, __} :> x]] &) /@ Union[data[[All, 3]]] Out[5]= {"string1" -> 1, "string2" -> 2, "string3" -> 3, "string4" -> 4} To explain: In[7]:= data[[All, 3]] Out[7]= {"string1", "string2", "string3", "string4", "string1", "string2", "string3", "string2", "string4"} Just gives alle occurrences of your strings (3rd components) in proper sequence. In[8]:= Union[data[[All, 3]]] Out[8]= {"string1", "string2", "string3", "string4"} Unifies and orders them. Now In[9]:= Cases[data, {_, x_, "string2", __}] Out[9]= {{1, 2, "string2", c, d}, {2, 2, "string2", c, d}, {4, 1, "string2", c, d}} gives all occurances with "string2", and In[10]:= Cases[data, {_, x_, "string2", __} :> x] Out[10]= {2, 2, 1} just retains the corresponding values of the 2nd component (in same order). In[11]:= Max[Cases[data, {_, x_, "string2", __} :> x]] Out[11]= 2 gives the Maximum of those. To do that for all values of the string we map this over the set of the strings: In[12]:= Max[Cases[data, {_, x_, #, __} :> x]] & /@ Union[data[[All, 3]]] Out[12]= {1, 2, 3, 4} Now which result corresponds to which string? If you have control of your bookkeeping (compare with Out[8]) you know, but it's better to be explicit, and show the associations: In[14]:= {Max[Cases[data, {_, x_, #, __} :> x]], #} & /@ Union[data[[All, 3]]] Out[14]= {{1, "string1"}, {2, "string2"}, {3, "string3"}, {4, "string4"}} or visually more pleasing as rules, as I did in Out[5]. -- Hartmut Wolf