Sort tenors in finance notation
<p>I have an array of tenors</p>

<pre><code>Tenors = np.array(['10Y', '15Y', '1M', '1Y', '20Y', '2Y', '30Y', '3M', '5Y', '6M', '9M'])
</code></pre>

<p>where <code>M</code> stands for month and <code>Y</code> stands for years. The correctly sorted order (ascending) would then be</p>

<pre><code>['1M', '3M', '6M', '9M', '1Y', '2Y', '5Y', '10Y', '15Y', '20Y', '30Y']
</code></pre>

<p>How do I achieve that using python with scipy/numpy? As the <code>tenors</code> originate from a <code>pandas</code> dataframe a solution based on <code>pandas</code> would be fine as well.</p>

<p>You can use <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.str.extract.html" rel="nofollow"><code>str.extract</code></a> for parsing numbers and values, then convert to <code>int</code> and <code>categories</code> by <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.astype.html" rel="nofollow"><code>astype</code></a> and last <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sort_values.html" rel="nofollow"><code>sort_values</code></a>:</p>

<pre><code>df = pd.DataFrame({'a':Tenors})
df[['b','c']] = df.a.str.extract("(\d+)([MY])", expand=True)
df.b = df.b.astype(int)
df.c = df.c.astype('category', ordered=True, categories=['M','Y'])
df = df.sort_values(['c','b'])
print (df)
      a   b  c
2    1M   1  M
7    3M   3  M
9    6M   6  M
10   9M   9  M
3    1Y   1  Y
5    2Y   2  Y
8    5Y   5  Y
0   10Y  10  Y
1   15Y  15  Y
4   20Y  20  Y
6   30Y  30  Y

print (df.a.tolist())
['1M', '3M', '6M', '9M', '1Y', '2Y', '5Y', '10Y', '15Y', '20Y', '30Y']
</code></pre>

python sorting pandas numpy finance