<p dir="auto">If you have a dataframe with a multiindex, and use groupby and then shift, using the frequency argument, the shifting fails, resulting in an empty result. For example:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy as np
import pandas as pd

dates1 = pd.date_range('2015-10-01', '2015-10-03')
df1 = pd.DataFrame(dict(grp='A', blah=[1,2,3]), index=dates1) .set_index('grp', append=True)

dates2 = pd.date_range('2015-10-02', '2015-10-04')
df2 = pd.DataFrame(dict(grp='B', blah=[10,np.nan,30]), index=dates2) .set_index('grp', append=True)

df = pd.concat([df1, df2])

In [ ]: df
Out[ ]: 
                blah
           grp      
2015-10-01 A       1
2015-10-02 A       2
2015-10-03 A       3
2015-10-02 B      10
2015-10-03 B     NaN
2015-10-04 B      30

# This works:
In [ ]: df.groupby(level='grp').shift(1)
Out[ ]: 
                blah
           grp      
2015-10-01 A     NaN
2015-10-02 A       1
2015-10-03 A       2
2015-10-02 B     NaN
2015-10-03 B      10
2015-10-04 B     NaN

# This fails:
In [ ]: df.groupby(level='grp').shift(1, freq='D')
Out[ ]: 
Empty DataFrame
Columns: []
Index: []"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">import</span> <span class="pl-s1">pandas</span> <span class="pl-k">as</span> <span class="pl-s1">pd</span>

<span class="pl-s1">dates1</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-en">date_range</span>(<span class="pl-s">'2015-10-01'</span>, <span class="pl-s">'2015-10-03'</span>)
<span class="pl-s1">df1</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>(<span class="pl-en">dict</span>(<span class="pl-s1">grp</span><span class="pl-c1">=</span><span class="pl-s">'A'</span>, <span class="pl-s1">blah</span><span class="pl-c1">=</span>[<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>]), <span class="pl-s1">index</span><span class="pl-c1">=</span><span class="pl-s1">dates1</span>) .<span class="pl-en">set_index</span>(<span class="pl-s">'grp'</span>, <span class="pl-s1">append</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)

<span class="pl-s1">dates2</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-en">date_range</span>(<span class="pl-s">'2015-10-02'</span>, <span class="pl-s">'2015-10-04'</span>)
<span class="pl-s1">df2</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>(<span class="pl-en">dict</span>(<span class="pl-s1">grp</span><span class="pl-c1">=</span><span class="pl-s">'B'</span>, <span class="pl-s1">blah</span><span class="pl-c1">=</span>[<span class="pl-c1">10</span>,<span class="pl-s1">np</span>.<span class="pl-s1">nan</span>,<span class="pl-c1">30</span>]), <span class="pl-s1">index</span><span class="pl-c1">=</span><span class="pl-s1">dates2</span>) .<span class="pl-en">set_index</span>(<span class="pl-s">'grp'</span>, <span class="pl-s1">append</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)

<span class="pl-s1">df</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-en">concat</span>([<span class="pl-s1">df1</span>, <span class="pl-s1">df2</span>])

<span class="pl-v">In</span> [<span class="pl-s1"></span> ]: <span class="pl-s1">df</span>
<span class="pl-v">Out</span>[<span class="pl-s1"></span> ]: 
                <span class="pl-s1">blah</span>
           <span class="pl-s1">grp</span>      
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">01</span> <span class="pl-v">A</span>       <span class="pl-c1">1</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">02</span> <span class="pl-v">A</span>       <span class="pl-c1">2</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">03</span> <span class="pl-v">A</span>       <span class="pl-c1">3</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">02</span> <span class="pl-v">B</span>      <span class="pl-c1">10</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">03</span> <span class="pl-v">B</span>     <span class="pl-v">NaN</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">04</span> <span class="pl-v">B</span>      <span class="pl-c1">30</span>

<span class="pl-c"># This works:</span>
<span class="pl-v">In</span> [<span class="pl-s1"></span> ]: <span class="pl-s1">df</span>.<span class="pl-en">groupby</span>(<span class="pl-s1">level</span><span class="pl-c1">=</span><span class="pl-s">'grp'</span>).<span class="pl-en">shift</span>(<span class="pl-c1">1</span>)
<span class="pl-v">Out</span>[<span class="pl-s1"></span> ]: 
                <span class="pl-s1">blah</span>
           <span class="pl-s1">grp</span>      
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">01</span> <span class="pl-v">A</span>     <span class="pl-v">NaN</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">02</span> <span class="pl-v">A</span>       <span class="pl-c1">1</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">03</span> <span class="pl-v">A</span>       <span class="pl-c1">2</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">02</span> <span class="pl-v">B</span>     <span class="pl-v">NaN</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">03</span> <span class="pl-v">B</span>      <span class="pl-c1">10</span>
<span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">04</span> <span class="pl-v">B</span>     <span class="pl-v">NaN</span>

<span class="pl-c"># This fails:</span>
<span class="pl-v">In</span> [<span class="pl-s1"></span> ]: <span class="pl-s1">df</span>.<span class="pl-en">groupby</span>(<span class="pl-s1">level</span><span class="pl-c1">=</span><span class="pl-s">'grp'</span>).<span class="pl-en">shift</span>(<span class="pl-c1">1</span>, <span class="pl-s1">freq</span><span class="pl-c1">=</span><span class="pl-s">'D'</span>)
<span class="pl-v">Out</span>[ ]: 
<span class="pl-v">Empty</span> <span class="pl-v">DataFrame</span>
<span class="pl-v">Columns</span>: []
<span class="pl-v">Index</span>: []</pre></div>
<p dir="auto">I'm not sure why, however using 'grp' as a column, it works fine:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="In [ ]: df.reset_index('grp').groupby('grp').shift(1, freq='D')
Out[ ]: 
                blah
grp                 
A   2015-10-02     1
    2015-10-03     2
    2015-10-04     3
B   2015-10-03    10
    2015-10-04   NaN
    2015-10-05    30"><pre class="notranslate"><span class="pl-v">In</span> [<span class="pl-s1"></span> ]: <span class="pl-s1">df</span>.<span class="pl-en">reset_index</span>(<span class="pl-s">'grp'</span>).<span class="pl-en">groupby</span>(<span class="pl-s">'grp'</span>).<span class="pl-en">shift</span>(<span class="pl-c1">1</span>, <span class="pl-s1">freq</span><span class="pl-c1">=</span><span class="pl-s">'D'</span>)
<span class="pl-v">Out</span>[<span class="pl-s1"></span> ]: 
                <span class="pl-s1">blah</span>
<span class="pl-s1">grp</span>                 
<span class="pl-v">A</span>   <span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">02</span>     <span class="pl-c1">1</span>
    <span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">03</span>     <span class="pl-c1">2</span>
    <span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">04</span>     <span class="pl-c1">3</span>
<span class="pl-v">B</span>   <span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">03</span>    <span class="pl-c1">10</span>
    <span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">04</span>   <span class="pl-v">NaN</span>
    <span class="pl-c1">2015</span><span class="pl-c1">-</span><span class="pl-c1">10</span><span class="pl-c1">-</span><span class="pl-c1">05</span>    <span class="pl-c1">30</span></pre></div>
<p dir="auto"><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="73313216" data-permission-text="Title is private" data-url="https://github.com/pandas-dev/pandas/issues/10063" data-hovercard-type="issue" data-hovercard-url="/pandas-dev/pandas/issues/10063/hovercard" href="https://github.com/pandas-dev/pandas/issues/10063">#10063</a> doesn't appear to have been completely fixed. While the exact example I gave now works (the resample), what if instead of a resample I had wanted to do a tshift? I would have wanted to be able to do <code class="notranslate">df.groupby(level='symbol').tshift(1, 'D')</code>, which still returns an empty DataFrame. Here, there's no aggregating in the time dimension so the TimeGrouper syntax that was the proposed solution wouldn't make sense.</p>
<p dir="auto">I also don't understand why the <code class="notranslate">df.groupby([pd.Grouper(level='symbol'), pd.Grouper(level='dt', freq='M')]).mean()</code> syntax is necessary instead of simply being able to do <code class="notranslate">df.groupby(level='symbol').resample('M', how='mean')</code>? The latter seems like much better design.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="df = DataFrame({'A' : 1 },index=pd.MultiIndex.from_product([list('ab'),date_range('20130101',periods=80)],names=['one','two']))
df.groupby([pd.Grouper(level='one'),pd.Grouper(level='two',freq='M')]).tshift(-1,'M')"><pre class="notranslate"><code class="notranslate">df = DataFrame({'A' : 1 },index=pd.MultiIndex.from_product([list('ab'),date_range('20130101',periods=80)],names=['one','two']))
df.groupby([pd.Grouper(level='one'),pd.Grouper(level='two',freq='M')]).tshift(-1,'M')
</code></pre></div>