<p>首先,将月日期字符串解析为Pandas时间戳:</p>
<pre><code>df['month'] = pd.to_datetime(df['month'], format='%Y-%m')
# month ticker b c
# 0 2014-01-01 AAU 10 0.04
# 1 2014-02-01 AAU 20 0.03
# 2 2014-03-01 AAU 13 0.06
# 3 2014-12-01 AAU 11 0.03
# 4 2014-01-01 ZZY 11 0.11
# 5 2014-02-01 ZZY 6 0.03
# 6 2014-12-01 ZZY 17 0.09
</code></pre>
<p>接下来,以月份作为索引,以ticker作为列级别,对DataFrame进行透视:</p>
<pre><code>df = df.pivot(index='month', columns='ticker')
# b c
# ticker AAU ZZY AAU ZZY
# month
# 2014-01-01 10 11 0.04 0.11
# 2014-02-01 20 6 0.03 0.03
# 2014-03-01 13 NaN 0.06 NaN
# 2014-12-01 11 17 0.03 0.09
</code></pre>
<p>通过现在旋转,我们以后可以更容易地向前填充每一列。</p>
<p>现在查找开始日期和结束日期:</p>
<pre><code>start_date = df.index.min() - pd.DateOffset(day=1)
end_date = df.index.max() + pd.DateOffset(day=31)
</code></pre>
<p>有趣的是,添加<code>pd.DateOffset(day=31)</code>并不总是导致日期在第31天结束。如果月份是二月,则添加<code>pd.DateOffset(day=31)</code>返回二月的最后一天:</p>
<pre><code>In [130]: pd.Timestamp('2014-2-28') + pd.DateOffset(day=31)
Out[130]: Timestamp('2014-02-28 00:00:00')
</code></pre>
<p>这很好,因为这意味着添加<code>pd.DateOffset(day=31)</code>将始终给我们一个月中最后一个有效日。</p>
<p>现在我们可以重新索引并向前填充数据帧:</p>
<pre><code>dates = pd.date_range(start_date, end_date, freq='D')
dates.name = 'date'
df = df.reindex(dates, method='ffill')
</code></pre>
<p>会产生</p>
<pre><code>In [160]: df.head()
Out[160]:
b c
ticker AAU ZZY AAU ZZY
date
2014-01-01 10 11 0.04 0.11
2014-01-02 10 11 0.04 0.11
2014-01-03 10 11 0.04 0.11
2014-01-04 10 11 0.04 0.11
2014-01-05 10 11 0.04 0.11
In [161]: df.tail()
Out[161]:
b c
ticker AAU ZZY AAU ZZY
date
2014-12-27 11 17 0.03 0.09
2014-12-28 11 17 0.03 0.09
2014-12-29 11 17 0.03 0.09
2014-12-30 11 17 0.03 0.09
2014-12-31 11 17 0.03 0.09
</code></pre>
<p>要将ticker移出列索引并移回列中,请执行以下操作:</p>
<pre><code>df = df.stack('ticker')
df = df.sortlevel(level=1)
df = df.reset_index()
</code></pre>
<hr/>
<p>所以把这些放在一起:</p>
<pre><code>import pandas as pd
df = pd.read_table('data', sep='\s+')
df['month'] = pd.to_datetime(df['month'], format='%Y-%m')
df = df.pivot(index='month', columns='ticker')
start_date = df.index.min() - pd.DateOffset(day=1)
end_date = df.index.max() + pd.DateOffset(day=31)
dates = pd.date_range(start_date, end_date, freq='D')
dates.name = 'date'
df = df.reindex(dates, method='ffill')
df = df.stack('ticker')
df = df.sortlevel(level=1)
df = df.reset_index()
</code></pre>
<p>收益率</p>
<pre><code>In [163]: df.head()
Out[163]:
date ticker b c
0 2014-01-01 AAU 10 0.04
1 2014-01-02 AAU 10 0.04
2 2014-01-03 AAU 10 0.04
3 2014-01-04 AAU 10 0.04
4 2014-01-05 AAU 10 0.04
In [164]: df.tail()
Out[164]:
date ticker b c
450 2014-12-27 ZZY 17 0.09
451 2014-12-28 ZZY 17 0.09
452 2014-12-29 ZZY 17 0.09
453 2014-12-30 ZZY 17 0.09
454 2014-12-31 ZZY 17 0.09
</code></pre>