<p dir="auto">Consider this very basic group by operation:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="df = pd.DataFrame({'col1': ['a', 'b', 'a', 'c'], 'col2': [1, 3, 2, 5]})
df_grp = df.groupby('col1')['col2']"><pre class="notranslate"><span class="pl-s1">df</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>({<span class="pl-s">'col1'</span>: [<span class="pl-s">'a'</span>, <span class="pl-s">'b'</span>, <span class="pl-s">'a'</span>, <span class="pl-s">'c'</span>], <span class="pl-s">'col2'</span>: [<span class="pl-c1">1</span>, <span class="pl-c1">3</span>, <span class="pl-c1">2</span>, <span class="pl-c1">5</span>]})
<span class="pl-s1">df_grp</span> <span class="pl-c1">=</span> <span class="pl-s1">df</span>.<span class="pl-en">groupby</span>(<span class="pl-s">'col1'</span>)[<span class="pl-s">'col2'</span>]</pre></div>
<p dir="auto">When aggregating using <code class="notranslate">mean</code>, <code class="notranslate">min</code>, ... (everything but <code class="notranslate">count</code>) the resulting Series has <code class="notranslate">col2</code> as its name:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="df_grp.mean()

col1
a       1.5
b       3.0
c       5.0
Name: col2, dtype: float64"><pre class="notranslate"><span class="pl-s1">df_grp</span>.<span class="pl-en">mean</span>()

<span class="pl-s1">col1</span>
<span class="pl-s1">a</span>       <span class="pl-c1">1.5</span>
<span class="pl-s1">b</span>       <span class="pl-c1">3.0</span>
<span class="pl-s1">c</span>       <span class="pl-c1">5.0</span>
<span class="pl-v">Name</span>: <span class="pl-s1">col2</span>, <span class="pl-s1">dtype</span>: <span class="pl-s1">float64</span></pre></div>
<p dir="auto">However, if I use <code class="notranslate">count</code> for aggregation, the name is not set:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="df_grp.count()

col1
a       2
b       1
c       1
dtype: int64"><pre class="notranslate"><span class="pl-s1">df_grp</span>.<span class="pl-en">count</span>()

<span class="pl-s1">col1</span>
<span class="pl-s1">a</span>       <span class="pl-c1">2</span>
<span class="pl-s1">b</span>       <span class="pl-c1">1</span>
<span class="pl-s1">c</span>       <span class="pl-c1">1</span>
<span class="pl-s1">dtype</span>: <span class="pl-s1">int64</span></pre></div>
<p dir="auto">Not a big problem for a simple case like that, but I stumbled over that while working with a MultiIndex that needed to be reindexed and led to a <code class="notranslate">KeyError</code> due to that missing column name.</p>
<p dir="auto">See <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="26263629" data-permission-text="Title is private" data-url="https://github.com/pandas-dev/pandas/issues/6068" data-hovercard-type="pull_request" data-hovercard-url="/pandas-dev/pandas/pull/6068/hovercard" href="https://github.com/pandas-dev/pandas/pull/6068">#6068</a></p>
<h2 dir="auto">Use case</h2>
<p dir="auto">Facilitate DataFrame group/apply transformations when using a function that returns a Series.  Right now, if we perform the following:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="import pandas
df = pandas.DataFrame(
        {'a':  [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2],
         'b':  [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
         'c':  [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
         'd':  [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
         })

def count_values(df):
    return pandas.Series({'count': df['b'].sum(), 'mean': df['c'].mean()}, name='metrics')

result = df.groupby('a').apply(count_values)
print result.stack().reset_index()"><pre class="notranslate"><code class="notranslate">import pandas
df = pandas.DataFrame(
        {'a':  [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2],
         'b':  [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
         'c':  [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
         'd':  [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
         })

def count_values(df):
    return pandas.Series({'count': df['b'].sum(), 'mean': df['c'].mean()}, name='metrics')

result = df.groupby('a').apply(count_values)
print result.stack().reset_index()
</code></pre></div>
<p dir="auto">We get the following output:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="   a level_1    0
0  0   count  2.0
1  0    mean  0.5
2  1   count  2.0
3  1    mean  0.5
4  2   count  2.0
5  2    mean  0.5

[6 rows x 3 columns]"><pre class="notranslate"><code class="notranslate">   a level_1    0
0  0   count  2.0
1  0    mean  0.5
2  1   count  2.0
3  1    mean  0.5
4  2   count  2.0
5  2    mean  0.5

[6 rows x 3 columns]
</code></pre></div>
<p dir="auto">Ideally, the series name should be preserved and propagated through these operations such that we get the following output:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="   a metrics    0
0  0   count  2.0
1  0    mean  0.5
2  1   count  2.0
3  1    mean  0.5
4  2   count  2.0
5  2    mean  0.5

[6 rows x 3 columns]"><pre class="notranslate"><code class="notranslate">   a metrics    0
0  0   count  2.0
1  0    mean  0.5
2  1   count  2.0
3  1    mean  0.5
4  2   count  2.0
5  2    mean  0.5

[6 rows x 3 columns]
</code></pre></div>
<p dir="auto">The only way to achieve this (currently) is:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="result = df.groupby('a').apply(count_values)
result.columns.name = 'metrics'
print result.stack().reset_index()"><pre class="notranslate"><code class="notranslate">result = df.groupby('a').apply(count_values)
result.columns.name = 'metrics'
print result.stack().reset_index()
</code></pre></div>
<p dir="auto">However, the key issue here is 1) this adds an extra line of code and 2) the name of the series created in the applied function may not be known in the outside block (so we can't properly fix the result.columns.name attribute).</p>
<p dir="auto">The other work-around is to name the index of the series:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="def count_values(df):
    series = pandas.Series({'count': df['b'].sum(), 'mean': df['c'].mean()})
    series.index.name = 'metrics'
    return series"><pre class="notranslate"><code class="notranslate">def count_values(df):
    series = pandas.Series({'count': df['b'].sum(), 'mean': df['c'].mean()})
    series.index.name = 'metrics'
    return series
</code></pre></div>
<p dir="auto">During the group/apply operation, one approach is to check to see whether series.index has the name attribute set.  If the name attribute is not set, it will set the index.name attribute to the name of the series (thus ensuring the name propagates).</p>