# Fastest/cleanest way to pad data with zero-data

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_] :=

Transpose[{xdata, ConstantArray[0., Length@xdata]}]},
Append[
Riffle[
Riffle[
Transpose[{xdata, ydata}]
],
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


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?

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

Why not use Dot and ArrayReshape on the original data:

data = DeveloperToPackedArray @ 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}

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

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

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


True

Original Post

data // {#.DiagonalMatrix[{1, 0}], #, #.DiagonalMatrix[{1, 0}]} & //Transpose //Catenate
`