title: Tableau error "All Fields must be aggregate or constant" when invoking TabPy SCRIPT_REAL
body: <p>I am calling a TabPy server via a calculated field in a Tableau worksheet to run a hypothesis test: does the rate of Bookings vary significantly by Group?</p>
  
  <p>I have a table such as:</p>
  
  <pre><code>     Group  Bookings
  0        A         1
  1        A         0
  3998     B         1
  3999     B         0
  </code></pre>
  
  <p>In Python, on the same server (<a href="https://github.com/erichannell/TabPy-docker" rel="nofollow noreferrer">using the python 2.7 docker image</a>) the test I want is simply:</p>
  
  <pre><code>from scipy.stats import fisher_exact
  df_cont_tbl = pd.crosstab(df['Group'], df['Bookings'])
  prop_test = fisher_exact(df_cont_tbl)
  print 'Fisher exact test: Odds ratio = {:.2f}, p-value = {:.3f}'.format(*prop_test)
  </code></pre>
  
  <p>Returns: <code>Fisher exact test: Odds ratio = 1.21, p-value = 0.102</code></p>
  
  <p>I connected Tableau to the TabPy server and can execute a hello-world calculated field. For example, I get 42 back with the calculated field: <code>SCRIPT_REAL("return 42", ATTR([Group]),ATTR([Bookings]) )</code> </p>
  
  <p>However, I try to invoke the stats function above with a calculated field to extract the p-value:</p>
  
  <pre><code>SCRIPT_REAL("
  import pandas as pd
  from scipy.stats import fisher_exact
  df_cont_tbl = pd.crosstab(_arg1, _arg2)
  prop_test = fisher_exact(df_cont_tbl)
  return prop_test[1]
  ", [Group], [Bookings] )
  </code></pre>
  
  <p>I get the notification: <em>The calculation contains errors</em> with the drop-down <em>All fields must be aggregate or constant when using table calculation functions or fields from multiple data sources</em></p>
  
  <p><a href="https://i.stack.imgur.com/F6AbJ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/F6AbJ.png" alt="error box"></a></p>
  
  <p>I tried wrapping the inputs with <code>ATTR()</code>, as in:</p>
  
  <pre><code>SCRIPT_REAL("
  import pandas as pd
  from scipy.stats import fisher_exact
  df_cont_tbl = pd.crosstab(_arg1, _arg2)
  prop_test = fisher_exact(df_cont_tbl)
  return prop_test[1]
  ",ATTR([Group]), ATTR([Bookings])
  )
  </code></pre>
  
  <p>Which changes the notification to "The calculation is valid" but returns a Pandas ValueError from the server:</p>
  
  <pre><code>An error occurred while communicating with the External Service.
  Error processing script
  Error when POST /evaluate: Traceback
  Traceback (most recent call last):
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/tabpy_server/tabpy.py", line 467, in post
  result = yield self.call_subprocess(function_to_evaluate, arguments)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/tornado/gen.py", line 1008, in run
  value = future.result()
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/tornado/concurrent.py", line 232, in result
  raise_exc_info(self._exc_info)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/tornado/gen.py", line 1014, in run
  yielded = self.gen.throw(*exc_info)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/tabpy_server/tabpy.py", line 488, in call_subprocess
  ret = yield future
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/tornado/gen.py", line 1008, in run
  value = future.result()
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/concurrent/futures/_base.py", line 400, in result
  return self.__get_result()
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/concurrent/futures/_base.py", line 359, in __get_result
  reraise(self._exception, self._traceback)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/concurrent/futures/_compat.py", line 107, in reraise
  exec('raise exc_type, exc_value, traceback', {}, locals_)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/concurrent/futures/thread.py", line 61, in run
  result = self.fn(*self.args, **self.kwargs)
  File "&lt;string&gt;", line 5, in _user_script
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/pandas/tools/pivot.py", line 479, in crosstab
  df = DataFrame(data)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/pandas/core/frame.py", line 266, in __init__
  mgr = self._init_dict(data, index, columns, dtype=dtype)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/pandas/core/frame.py", line 402, in _init_dict
  return _arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/pandas/core/frame.py", line 5398, in _arrays_to_mgr
  index = extract_index(arrays)
  File "/opt/conda/envs/Tableau-Python-Server/lib/python2.7/site-packages/pandas/core/frame.py", line 5437, in extract_index
  raise ValueError('If using all scalar values, you must pass'
  ValueError: If using all scalar values, you must pass an index
  Error type : ValueError
  Error message : If using all scalar values, you must pass an index
  </code></pre>
  
  <h2>Example dataset:</h2>
  
  <p>To generate the CSV I am connecting to:</p>
  
  <pre><code>import os
  import pandas as pd
  import numpy as np
  from collections import namedtuple
  
  OUTPUT_LOC = os.path.expanduser('~/TabPy_demo/ab_test_demo_results.csv')
  
  GroupObs = namedtuple('GroupObs', ['name','n','p'])
  
  obs = [GroupObs('A',3000,.10),GroupObs('B',1000,.13)] 
  # note true odds ratio = (13/87)/(10/90) = 1.345
  
  np.random.seed(2019)
  
  df = pd.concat( [ pd.DataFrame({'Group': grp.name,
                                  'Bookings':  pd.Series(np.random.binomial(n=1, 
                                                              p=grp.p, size=grp.n))
                                }) for grp in obs
                    ],ignore_index=True )
  
  df.to_csv(OUTPUT_LOC,index=False)
  </code></pre>