I'm not sure about directly doing it with Pandas, but you can do this easily enough if you don't mind using numpy.diag()
to build the diagonal data matrix for your series and then plugging that into a DataFrame:
diag_data = np.diag(s) # don't need s.as_matrix(), turns out
df = pd.DataFrame(diag_data, index=s.index, columns=s.index)
a b c
a 1 0 0
b 0 2 0
c 0 0 3
In one line:
df = pd.DataFrame(np.diag(s),
index=s.index,
columns=s.index)
Timing comparison with a Series made from a random array of 10000 elements:
s = pd.Series(np.random.rand(10000), index=np.arange(10000))
df = pd.DataFrame(np.diag(s), ...)
173 ms ± 2.91 ms per loop (mean ± std. dev. of 7 runs, 20 loops each)
df = pd.DataFrame(0, ...)
np.fill_diagonal(df.values, s)
212 ms ± 909 µs per loop (mean ± std. dev. of 7 runs, 20 loops each)
mat = np.zeros(...)
np.fill_diagonal(mat, s)
df = pd.DataFrame(mat, ...)
175 ms ± 3.72 ms per loop (mean ± std. dev. of 7 runs, 20 loops each)
It looks like the first and third option shown here are essentially the same, while the middle option is the slowest.