Fastest/cleanest way to pad data with zero-data

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}


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