# Filling in explicit zeros in a (x,y) list for nonexisting y values for discrete Fourier transform in Mathematica

I have a list of (x,y) values in Mathematica for various discrete x values, as in

intensities={{26, 10}, {27, 289}, {28, 90}, {29, 1079}, {30, 30}, {33, 10}, {39,
179}, {40, 40}, {41, 2269}}


I would now like to insert into this list explicit zeros for each discrete value of x that has a nonexisting y value, as in

intensities2={{0,0},{1,0},{2,0},....,{26,10},{27,289},{28,90},...,{41,2269}}


Out of these I would then like to extract just the y values to be able to do a discrete Forier transform on them. Any thoughts how I could do this most efficiently?

cheers & many thanks for any advice! Tom

-
Something like this can be used to get zeroes with specific values altered. ilist = ConstantArray[0, Max[intensities[[All, 1]]]]; Map[(ilist[[#[[1]] + 1]] = #[[2]]) &, intensities]; – Daniel Lichtblau Nov 6 '13 at 17:35
@PlatoManiac: yes, sorry - I edited it now... – Tom Wenseleers Nov 6 '13 at 17:41
@DanielLichtblau, since Tom wants the x values to start at 0, shouldn't you use ilist=ConstantArray[0,1+intensities[[-1,1]]];Map[(ilist[[#[[1]]+1]]=#[[2]])&,in‌​tensities]; ? This then gives ilist as the answer Tom wants I think. This is a simpler solution than the one I posted below, but after all these years I still find the myriad uses of Map hard to understand. – JasonB Nov 6 '13 at 17:45
@JasonB Yes one can alter that code to get a list of ordered pairs. I had indeed skipped that and gone directly to "extract[ing] just the y values". – Daniel Lichtblau Nov 6 '13 at 18:16

Normal@SparseArray[{#1} -> #2 & @@@ intensities]


Be careful that it works if the list intensities2 starts with {1,x} not {0,x} and input list intensities has no entries like {0,x}.

If you persist on starting intensities2 with {0,x} and given that input list intensities will have increasing x values then try the following

With[{zero = First@#},
If[zero[[1]] === 0,
({zero[[2]]}~Join~SparseArray[{#1} -> #2 & @@@ Rest[#]]),
{0}~Join~SparseArray[{#1} -> #2 & @@@ #]
]
] &@intensities; // AbsoluteTiming


In order to check efficiency you will need to create bigger example data. You can do so using the following.

samplesize = 10^6;
intensities =Sort@Transpose@(RandomSample[#,samplesize] &/@
(Range[0, #] & /@ {10 samplesize,10 samplesize}));

-
Many thanks for this - brilliant! I like the other answers too, but this one is really compact! I always have trouble coming up with such compact solutions, typically resorting to old school Do loops :-) – Tom Wenseleers Nov 6 '13 at 17:49
Slick (and an upvote). – Daniel Lichtblau Nov 6 '13 at 18:17

belisarius's answer is more elegant I'm sure, but I like a straightforward use of Table and Do whenever possible.

intensities={{26,10},{27,289},{28,90},{29,1079},{30,30},{33,10},{39,179},{40,40},{41,2269}};
intensities2=Table[{n,0},{n,0,intensities[[-1,1]]}];
Do[
intensities2[[intensities[[n,1]]+1]]=intensities[[n]];
,{n,Length[intensities]}]


Then when you want to extract just the second column of the data, just the y values, you use

intensities2[[All,2]]

-
(Join[{#, 0} & /@ Complement[Range@Max@#[[All, 1]], #[[All, 1]]], #] &@ints)[[All,2]]

-
in your post, is ints equal to OP's intensities? Also, it seemed to work better before the edit, although it didn't give the {0,0} element. When I enter what you have now, I only get the second column. – JasonB Nov 6 '13 at 17:36
@JasonB "Out of these I would then like to extract just the y values" ... – Dr. belisarius Nov 6 '13 at 17:49
yeah I saw that after I made this comment. I'm still confused about whether the OP needed the x values to start at 0 or 1. In his question it seemed that he wanted it to start at 0, so the resulting answer should be a one-dimensional list with 42 elements. But the answer he accepted doesn't fit that criteria. – JasonB Nov 6 '13 at 17:53
@JasonB I edited my answer to fit the case you mentioned. – PlatoManiac Nov 6 '13 at 18:45
@JasonB Me neither, but it's his question :) – Dr. belisarius Nov 6 '13 at 19:28