4
$\begingroup$

I have a two-dimensional list of data pairs {x,y} where the first column in the pair sometimes contains a unique "tag". When this tag is found using Cases, the value in y is returned.

A sample of this data is given here:

    sample={{{0.057, 574}, {"CH4", 25831.9}, {"C2H6", 0.0231548},{"C2H2", 
   0.000066748}}, {{"CH4", 25722.}, {"C2H6", 0.023806}}, {{"CH4", 
   24290.8}, {"C2H6", 0.345365}, {"C2H4", 0.400931}, {2.122, 
   4391}, {"C2H2", 0.0964659}, {3.123, 16139}, {3.26, 67}, {5.219, 
   4116}, {5.629, 298}, {6.054, 251}, {7.109, 187}, {7.217, 
   33246}, {$Failed, 3870}, {8.605, 12177}}, {{"CH4", 
   24074.3}, {"C2H6", 0.34487}, {"C2H4", 0.388133}, {2.124, 
   5206}, {2.22, 1754}, {2.453, 219}, {"C2H2", 0.0903442}, {2.895, 
   545}, {3.124, 15727}, {3.396, 540}, {3.489, 125}, {5.222, 
   4186}, {5.634, 311}, {6.375, 21249}, {7.109, 108}, {7.22, 
   30703}, {7.654, 3772}, {8.612, 11314}, {9.677, 3225}}}

So, I want to apply a search using Cases, for example for "C2H4" in the first column and return the corresponding value in the second column.

My code to do this is:

list = Table[Cases[sample[[i]], {x_, y_} /; x == "C2H4" :> y ],{i,1,Length[sample]}]

However, this returns the list:

{{}, {}, {0.400931}, {0.388133}}

I would like to replace the first two blank elements of this list with zeroes, for preference, I would like to do this within the "Cases" function that I have defined.

I can't seem to make anything work. Any ideas...?

Cheers! :)

$\endgroup$
  • 5
    $\begingroup$ So, Replace[Cases[#, {"C2H4", y_} :> y], {} -> 0] & /@ sample? $\endgroup$ – J. M. will be back soon May 17 '17 at 15:32
  • $\begingroup$ The empty lists are due to the tag not appearing in the first two sublists. You could flatten the data first: getValues[data_, tag_] := Select[Flatten[data, 1], #[[1]] === tag &][[All, 2]]. Call with getValues[sample,"C2H4"] $\endgroup$ – David Keith May 17 '17 at 16:19
  • $\begingroup$ Thanks JM and David for your responses. I applied JM's suggestion in the end. The answer was frustratingly simple! $\endgroup$ – Butters May 18 '17 at 12:14
1
$\begingroup$
sample = {{{0.057, 574}, {"CH4", 25831.9}, {"C2H6", 
     0.0231548}, {"C2H2", 0.000066748}}, {{"CH4", 25722.}, {"C2H6", 
     0.023806}}, {{"CH4", 24290.8}, {"C2H6", 0.345365}, {"C2H4", 
     0.400931}, {2.122, 4391}, {"C2H2", 0.0964659}, {3.123, 
     16139}, {3.26, 67}, {5.219, 4116}, {5.629, 298}, {6.054, 
     251}, {7.109, 187}, {7.217, 33246}, {$Failed, 3870}, {8.605, 
     12177}}, {{"CH4", 24074.3}, {"C2H6", 0.34487}, {"C2H4", 
     0.388133}, {2.124, 5206}, {2.22, 1754}, {2.453, 219}, {"C2H2", 
     0.0903442}, {2.895, 545}, {3.124, 15727}, {3.396, 540}, {3.489, 
     125}, {5.222, 4186}, {5.634, 311}, {6.375, 21249}, {7.109, 
     108}, {7.22, 30703}, {7.654, 3772}, {8.612, 11314}, {9.677, 
     3225}}};
tags = DeleteDuplicates@Cases[sample, _String, {-1}]

{"CH4", "C2H6", "C2H2", "C2H4"}

If just zeros need to be where there are no instances of the tag

tagsearch1[tag_] := If[Count[#, {tag, _}] == 0, 0., Cases[#, {tag, y_} :> y]] & /@ sample
tagsearch2[tag_] := (Cases[{tag, y_} :> y] /@ sample) /. {} -> 0.

tagsearch1["C2H4"]
tagsearch2["C2H4"] == %

{0., 0., {0.400931}, {0.388133}}

True

If the output should be a full array (i.e. ArrayQ returns True or e.g. 1D, 2D, 3D, ...)

tagsearch3[tag_] := Join @@ (If[Count[#, {tag, _}] == 0, {0.}, Cases[#, {tag, y_} :> y]] & /@ sample)
tagsearch4[tag_] := Join @@ ((Cases[{tag, y_} :> y] /@ sample) /. {} -> {0.})
tagsearch5[tag_] := Replace[(Cases[{tag, y_} :> y] /@ sample) /. {} -> 0., List -> Sequence, {2}, Heads -> True]
f[tag_] := Fold[Insert[#1, 0., #2] &, Cases[sample, {tag, y_} :> y, {-2}], Position[Count[{tag, _}] /@ sample, 0]]
(*The idea behind f was to not do any replacements, aside from the one in Cases*)

tagsearch3["C2H4"]
tagsearch3["C2H4"] == tagsearch4["C2H4"] == tagsearch5["C2H4"] == f["C2H4"] == %

{0., 0., 0.400931, 0.388133}

True

And for a timing comparison

Block[{sample = Join @@ ConstantArray[sample, 10^4]}, {ToString@#, RepeatedTiming[# /@ tags][[1]]} & /@ {tagsearch1, tagsearch2, tagsearch3, tagsearch4, tagsearch5, f}]

(*{tagsearch1,0.778}
{tagsearch2,0.344}
{tagsearch3,0.763}
{tagsearch4,0.339}
{tagsearch5,0.371}
{f,1.6}*)

So, turns out Occam was right, a simple Join @@ ((Cases[{tag, y_} :> y] /@ sample) /. {} -> {0.}) is the best of these options, and it gives

tagsearch4 /@ tags

{{25831.9, 25722., 24290.8, 24074.3}, {0.0231548, 0.023806, 0.345365, 0.34487}, {0.000066748, 0., 0.0964659, 0.0903442}, {0., 0., 0.400931, 0.388133}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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