8
$\begingroup$

I want to pad a set of data in {x, y} pairs with {x, 0}, {x, 0} on each side of each data point.

I know I can do this like so:

zeroPaddedData[xdata_, ydata_] :=

 With[{padding = 
    Transpose[{xdata, ConstantArray[0., Length@xdata]}]},
  Append[
   Riffle[
    Riffle[
     padding,
     Transpose[{xdata, ydata}]
     ],
    padding,
    3
    ],
   {xdata[[-1]], 0.}
   ]
  ]

which, for example, gives:

zpd = zeroPaddedData @@ Transpose@Table[{x, Sin[x]}, {x, 0, 2 Pi, .5}]

{{0., 0.}, {0., 0.}, {0., 0.}, {0.5, 0.}, {0.5, 0.479426}, {0.5, 
  0.}, {1., 0.}, {1., 0.841471}, {1., 0.}, {1.5, 0.}, {1.5, 
  0.997495}, {1.5, 0.}, {2., 0.}, {2., 0.909297}, {2., 0.}, {2.5, 
  0.}, {2.5, 0.598472}, {2.5, 0.}, {3., 0.}, {3., 0.14112}, {3., 
  0.}, {3.5, 0.}, {3.5, -0.350783}, {3.5, 0.}, {4., 
  0.}, {4., -0.756802}, {4., 0.}, {4.5, 0.}, {4.5, -0.97753}, {4.5, 
  0.}, {5., 0.}, {5., -0.958924}, {5., 0.}, {5.5, 
  0.}, {5.5, -0.70554}, {5.5, 0.}, {6., 0.}, {6., -0.279415}, {6., 0.}}

Which will plot out like so:

zpd // ListLinePlot

enter image description here

But this is slow over larger data sets:

dats = Transpose@Table[{x, Sin[x]}, {x, 0, 2 Pi, .001}];

zeroPaddedData @@ dats // RepeatedTiming // First

0.0039

How can I do this faster/cleaner?

$\endgroup$
  • $\begingroup$ Is zpd not ending with {6., 0.} deliberate? $\endgroup$ – J. M. is in limbo Oct 19 '18 at 7:34
  • $\begingroup$ @J.M.iscomputer-less nope I just accidentally a result from before I added the Append $\endgroup$ – b3m2a1 Oct 19 '18 at 7:35
6
$\begingroup$

Why not use Dot and ArrayReshape on the original data:

data = Developer`ToPackedArray @ Table[
    {x, Sin[x]},
    {x, 0, 2Pi, .0001}
];

Then:

ArrayReshape[
    data . {{1, 0, 1, 0, 1, 0}, {0, 0, 0, 1, 0, 0}},
    {Length[data] 3, 2}
]; //RepeatedTiming

{0.000397, Null}

$\endgroup$
5
$\begingroup$

One reason for slowness is that the input data was not packed. Moreover Transpose is often faster than Riffle:

{xdata, ydata} = Transpose[Map[x \[Function] {x, Sin[x]}, Range[0., 2 Pi, .0001]]];

f[xdata_, ydata_] := Transpose[{
   Flatten[Transpose[ConstantArray[xdata, 3]]],
   With[{o = ConstantArray[0., Length[ydata]]},
    Flatten[Transpose[{o, ydata, o}]]
    ]
   }]

a = zeroPaddedData[xdata, ydata]; // RepeatedTiming // First
b = f[xdata, ydata]; // RepeatedTiming // First
a == b

0.030

0.00165

True

$\endgroup$
4
$\begingroup$

Slower but simple

tab = Table[{x, Sin[x]}, {x, 0, 2 Pi, .5}];
SequenceReplace[tab, {{a_,b_}}:>Sequence[{a,0},{a,b},{a,0}]] == zpd

True

Update: Using Upsample on the second argument gives a slight improvement over Henrik's f:

ClearAll[zPad]
zPad[xd_, yd_] := Transpose[{Flatten[ConstantArray[xd, 3], {2, 1}], Upsample[yd, 3, 2]}];

{xdata, ydata} = Transpose[Map[x \[Function] {x, Sin[x]}, Range[0., 2 Pi, .0001]]]; 
a = zeroPaddedData[xdata, ydata]; // RepeatedTiming // First

0.024

b = f[xdata, ydata]; // RepeatedTiming // First

0.0017

c = zPad[xdata, ydata]; // RepeatedTiming // First 

0.0016

a == b == c

True

Interesting to note that although Upsample is almost twice as fast as With[{o = ConstantArray[0., Length[ydata]]}, Flatten[Transpose[{o, ydata, o}] ]] this advantage is not retained when combined with other steps:

r1 = Upsample[ydata, 3, 2] ; // RepeatedTiming // First

0.00061

r2 = With[{o = ConstantArray[0., Length[ydata]]}, 
     Flatten[Transpose[{o, ydata, o}] ]]; // RepeatedTiming // First 

0.0013

r1 == r2

True

$\endgroup$
0
$\begingroup$
With[{a = data.DiagonalMatrix[{1, 0}]}, {a, data, a} // Transpose //Catenate] == zpd

True

Original Post

data // {#.DiagonalMatrix[{1, 0}], #, #.DiagonalMatrix[{1, 0}]} & //Transpose //Catenate
$\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.