<p dir="auto">Using the built-in <code class="notranslate">sum</code> function gives correct result in <code class="notranslate">df.agg(sum, axis=0)</code>, but wrong result in <code class="notranslate">df.agg(sum, axis=1)</code>.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; df = pd.DataFrame([[np.nan, 2], [3, 4]])
&gt;&gt;&gt; df.agg(sum, axis=0)
0    3.0
1    6.0
dtype: float64
&gt;&gt;&gt; df.agg(sum, axis=1)
0    NaN
1    7.0
dtype: float64"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <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-s1">np</span>.<span class="pl-s1">nan</span>, <span class="pl-c1">2</span>], [<span class="pl-c1">3</span>, <span class="pl-c1">4</span>]])
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">df</span>.<span class="pl-en">agg</span>(<span class="pl-s1">sum</span>, <span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-c1">0</span>)
<span class="pl-c1">0</span>    <span class="pl-c1">3.0</span>
<span class="pl-c1">1</span>    <span class="pl-c1">6.0</span>
<span class="pl-s1">dtype</span>: <span class="pl-s1">float64</span>
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">df</span>.<span class="pl-en">agg</span>(<span class="pl-s1">sum</span>, <span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-c1">1</span>)
<span class="pl-c1">0</span>    <span class="pl-v">NaN</span>
<span class="pl-c1">1</span>    <span class="pl-c1">7.0</span>
<span class="pl-s1">dtype</span>: <span class="pl-s1">float64</span></pre></div>
<p dir="auto">The <code class="notranslate">NaN</code> in the last example should be 2.0.</p>
<p dir="auto">Also, operation using the builtin <code class="notranslate">sum</code> in <code class="notranslate">agg</code> with <code class="notranslate">axis=1</code> are very slow:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; n = 1_000
&gt;&gt;&gt; df = pd.DataFrame({'a': range(n), 'b': range(n)})
&gt;&gt;&gt; %timeit df.agg(sum, axis=1)
16.5 ms ± 25.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
&gt;&gt;&gt; %timeit df.T.agg(sum)  # correct result *and* faster
312 µs ± 3.17 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">n</span> <span class="pl-c1">=</span> <span class="pl-c1">1_000</span>
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <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">'a'</span>: <span class="pl-en">range</span>(<span class="pl-s1">n</span>), <span class="pl-s">'b'</span>: <span class="pl-en">range</span>(<span class="pl-s1">n</span>)})
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-c1">%</span><span class="pl-s1">timeit</span> <span class="pl-s1">df</span>.<span class="pl-en">agg</span>(<span class="pl-s1">sum</span>, <span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-c1">1</span>)
<span class="pl-c1">16.5</span> <span class="pl-s1">ms</span> ± <span class="pl-c1">25.5</span> <span class="pl-s1">µs</span> <span class="pl-s1">per</span> <span class="pl-en">loop</span> (<span class="pl-s1">mean</span> ± <span class="pl-s1">std</span>. <span class="pl-s1">dev</span>. <span class="pl-s1">of</span> <span class="pl-c1">7</span> <span class="pl-s1">runs</span>, <span class="pl-c1">100</span> <span class="pl-s1">loops</span> <span class="pl-s1">each</span>)
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-c1">%</span><span class="pl-s1">timeit</span> <span class="pl-s1">df</span>.<span class="pl-v">T</span>.<span class="pl-en">agg</span>(<span class="pl-s1">sum</span>)  <span class="pl-c"># correct result *and* faster</span>
<span class="pl-c1">312</span> <span class="pl-s1">µs</span> ± <span class="pl-c1">3.17</span> <span class="pl-s1">µs</span> <span class="pl-s1">per</span> <span class="pl-en">loop</span> (<span class="pl-s1">mean</span> ± <span class="pl-s1">std</span>. <span class="pl-s1">dev</span>. <span class="pl-s1">of</span> <span class="pl-c1">7</span> <span class="pl-s1">runs</span>, <span class="pl-c1">1000</span> <span class="pl-s1">loops</span> <span class="pl-s1">each</span>)</pre></div>
<h4 dir="auto">Problem description</h4>
<p dir="auto">Currently, <code class="notranslate">df.agg(func, axis=1)</code> defers to <code class="notranslate">df.apply(func, axis=1)</code>. This is not done for <code class="notranslate">axis=0</code>, and the operation may therefore give unexpected results and slow the operation down (because <code class="notranslate">df.apply</code> can be very slow).</p>
<h4 dir="auto">Expected Output</h4>
<p dir="auto">The expected output is:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; df.agg(sum, axis=1)
0    2.0
1    7.0
dtype: float64"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">df</span>.<span class="pl-en">agg</span>(<span class="pl-s1">sum</span>, <span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-c1">1</span>)
<span class="pl-c1">0</span>    <span class="pl-c1">2.0</span>
<span class="pl-c1">1</span>    <span class="pl-c1">7.0</span>
<span class="pl-s1">dtype</span>: <span class="pl-s1">float64</span></pre></div>
<h4 dir="auto">Solution proposal</h4>
<p dir="auto">I'm thinking about putting in <code class="notranslate">df.T.agg(func, axis=0)</code> rather than <code class="notranslate">df.apply(func, axis=1)</code> in a few strategic places. This should ensure both getting correct results and faster operations. will report back if this succeeds.</p>
<h4 dir="auto">Code Sample</h4>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy
import pandas

numpy.random.seed(1234)

frame = pandas.DataFrame(
    data=numpy.random.random((5, 3))
)
print(
    frame
)
# Works
print(
    frame.agg(['mean', 'std'])
)
# Expected output
print(
    frame.transpose().agg(['mean', 'std']).transpose()
)
# Does not work as expected
print(
    frame.agg(['mean', 'std'], axis=1)
)
"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span>
<span class="pl-k">import</span> <span class="pl-s1">pandas</span>

<span class="pl-s1">numpy</span>.<span class="pl-s1">random</span>.<span class="pl-en">seed</span>(<span class="pl-c1">1234</span>)

<span class="pl-s1">frame</span> <span class="pl-c1">=</span> <span class="pl-s1">pandas</span>.<span class="pl-v">DataFrame</span>(
    <span class="pl-s1">data</span><span class="pl-c1">=</span><span class="pl-s1">numpy</span>.<span class="pl-s1">random</span>.<span class="pl-en">random</span>((<span class="pl-c1">5</span>, <span class="pl-c1">3</span>))
)
<span class="pl-en">print</span>(
    <span class="pl-s1">frame</span>
)
<span class="pl-c"># Works</span>
<span class="pl-en">print</span>(
    <span class="pl-s1">frame</span>.<span class="pl-en">agg</span>([<span class="pl-s">'mean'</span>, <span class="pl-s">'std'</span>])
)
<span class="pl-c"># Expected output</span>
<span class="pl-en">print</span>(
    <span class="pl-s1">frame</span>.<span class="pl-en">transpose</span>().<span class="pl-en">agg</span>([<span class="pl-s">'mean'</span>, <span class="pl-s">'std'</span>]).<span class="pl-en">transpose</span>()
)
<span class="pl-c"># Does not work as expected</span>
<span class="pl-en">print</span>(
    <span class="pl-s1">frame</span>.<span class="pl-en">agg</span>([<span class="pl-s">'mean'</span>, <span class="pl-s">'std'</span>], <span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-c1">1</span>)
)</pre></div>
<h4 dir="auto">Problem description</h4>
<p dir="auto">Calling the <code class="notranslate">agg</code> method on a frame with <code class="notranslate">axis=1</code> raises a <code class="notranslate">TypeError</code>:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
Traceback (most recent call last):
  File &quot;/home/lafras/tmp/buggy.py&quot;, line 13, in &lt;module&gt;
    frame.agg(['mean', 'std'], axis=1)
  File &quot;/home/lafras/.local/lib/python3.5/site-packages/pandas/core/frame.py&quot;, line 4154, in aggregate
    return self.apply(func, axis=axis, args=args, **kwargs)
  File &quot;/home/lafras/.local/lib/python3.5/site-packages/pandas/core/frame.py&quot;, line 4262, in apply
    ignore_failures=ignore_failures)
  File &quot;/home/lafras/.local/lib/python3.5/site-packages/pandas/core/frame.py&quot;, line 4358, in _apply_standard
    results[i] = func(v)
TypeError: (&quot;'list' object is not callable&quot;, 'occurred at index 0')
"><pre class="notranslate"><span class="pl-v">Traceback</span> (<span class="pl-s1">most</span> <span class="pl-s1">recent</span> <span class="pl-s1">call</span> <span class="pl-s1">last</span>):
  <span class="pl-v">File</span> <span class="pl-s">"/home/lafras/tmp/buggy.py"</span>, <span class="pl-s1">line</span> <span class="pl-c1">13</span>, <span class="pl-s1">in</span> <span class="pl-c1">&lt;</span><span class="pl-s1">module</span><span class="pl-c1">&gt;</span>
    <span class="pl-s1">frame</span>.<span class="pl-en">agg</span>([<span class="pl-s">'mean'</span>, <span class="pl-s">'std'</span>], <span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-c1">1</span>)
  <span class="pl-v">File</span> <span class="pl-s">"/home/lafras/.local/lib/python3.5/site-packages/pandas/core/frame.py"</span>, <span class="pl-s1">line</span> <span class="pl-c1">4154</span>, <span class="pl-s1">in</span> <span class="pl-s1">aggregate</span>
    <span class="pl-k">return</span> <span class="pl-s1">self</span>.<span class="pl-en">apply</span>(<span class="pl-s1">func</span>, <span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-s1">axis</span>, <span class="pl-s1">args</span><span class="pl-c1">=</span><span class="pl-s1">args</span>, <span class="pl-c1">**</span><span class="pl-s1">kwargs</span>)
  <span class="pl-v">File</span> <span class="pl-s">"/home/lafras/.local/lib/python3.5/site-packages/pandas/core/frame.py"</span>, <span class="pl-s1">line</span> <span class="pl-c1">4262</span>, <span class="pl-s1">in</span> <span class="pl-s1">apply</span>
    <span class="pl-s1">ignore_failures</span><span class="pl-c1">=</span><span class="pl-s1">ignore_failures</span>)
  <span class="pl-v">File</span> <span class="pl-s">"/home/lafras/.local/lib/python3.5/site-packages/pandas/core/frame.py"</span>, <span class="pl-s1">line</span> <span class="pl-c1">4358</span>, <span class="pl-s1">in</span> <span class="pl-s1">_apply_standard</span>
    <span class="pl-s1">results</span>[<span class="pl-s1">i</span>] <span class="pl-c1">=</span> <span class="pl-en">func</span>(<span class="pl-s1">v</span>)
<span class="pl-v">TypeError</span>: (<span class="pl-s">"'list' object is not callable"</span>, <span class="pl-s">'occurred at index 0'</span>)</pre></div>
<h4 dir="auto">Expected Output</h4>
<p dir="auto"><code class="notranslate">frame.agg(['mean', 'std'], axis=1)</code> should produce this:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="       mean       std
0  0.417119  0.216033
1  0.612642  0.294504
2  0.678825  0.357107
3  0.578248  0.267557
4  0.588805  0.189838"><pre class="notranslate"><code class="notranslate">       mean       std
0  0.417119  0.216033
1  0.612642  0.294504
2  0.678825  0.357107
3  0.578248  0.267557
4  0.588805  0.189838
</code></pre></div>
<h4 dir="auto">Output of <code class="notranslate">pd.show_versions()</code></h4>
<details>
INSTALLED VERSIONS
------------------
commit: None
python: 3.5.2.final.0
python-bits: 64
OS: Linux
OS-release: 4.4.0-79-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_ZA.UTF-8
LOCALE: en_ZA.UTF-8
<p dir="auto">pandas: 0.20.2<br>
pytest: 3.0.4<br>
pip: 9.0.1<br>
setuptools: 36.0.1<br>
Cython: 0.25.2<br>
numpy: 1.13.0<br>
scipy: 0.19.0<br>
xarray: 0.8.2<br>
IPython: 6.1.0<br>
sphinx: None<br>
patsy: 0.4.1<br>
dateutil: 2.6.0<br>
pytz: 2017.2<br>
blosc: None<br>
bottleneck: None<br>
tables: 3.3.0<br>
numexpr: 2.6.1<br>
feather: None<br>
matplotlib: 2.0.0<br>
openpyxl: None<br>
xlrd: 1.0.0<br>
xlwt: None<br>
xlsxwriter: None<br>
lxml: None<br>
bs4: 4.4.1<br>
html5lib: 0.9999999<br>
sqlalchemy: None<br>
pymysql: None<br>
psycopg2: None<br>
jinja2: 2.9.5<br>
s3fs: 0.0.7<br>
pandas_gbq: None<br>
pandas_datareader: 0.2.1</p>
</details>