prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  numpy scalar in Dataframe not JSON serializable
  Is it possible to allow numpy scalars in a dataframe?
  
  The following code is not working, because a np.array is not json serializable:
  
  ```
  df_numpy = pd.DataFrame([dict(
          x=np.array(1),
          y=np.array(2),
          )])
  Chart(df_numpy).encode(x='x', y='y')
  # TypeError: array(1) is not JSON serializable
  ```
  
  Full Example: [
  https://github.com/boeddeker/ipynb/blob/master/bug_altair_numpy.ipynb](https://github.com/boeddeker/ipynb/blob/master/bug_altair_numpy.ipynb)
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `altair/utils/core.py`
  Content:
  ```
  1 """
  2 Utility routines
  3 """
  4 import re
  5 import warnings
  6 
  7 import pandas as pd
  8 import numpy as np
  9 
  10 
  11 TYPECODE_MAP = {'ordinal': 'O',
  12                 'nominal': 'N',
  13                 'quantitative': 'Q',
  14                 'temporal': 'T'}
  15 
  16 INV_TYPECODE_MAP = {v: k for k, v in TYPECODE_MAP.items()}
  17 
  18 TYPE_ABBR = TYPECODE_MAP.values()
  19 
  20 
  21 def parse_shorthand(shorthand):
  22     """
  23     Parse the shorthand expression for aggregation, field, and type.
  24 
  25     These are of the form:
  26 
  27     - "col_name"
  28     - "col_name:O"
  29     - "average(col_name)"
  30     - "average(col_name):O"
  31 
  32     Parameters
  33     ----------
  34     shorthand: str
  35         Shorthand string
  36 
  37     Returns
  38     -------
  39     D : dict
  40         Dictionary containing the field, aggregate, and typecode
  41     """
  42     if not shorthand:
  43         return {}
  44 
  45     # Must import this here to avoid circular imports
  46     from ..schema import AggregateOp
  47     valid_aggregates = AggregateOp().values
  48     valid_typecodes = list(TYPECODE_MAP) + list(INV_TYPECODE_MAP)
  49 
  50     # build regular expressions
  51     units = dict(field='(?P<field>.*)',
  52                  type='(?P<type>{0})'.format('|'.join(valid_typecodes)),
  53                  aggregate='(?P<aggregate>{0})'.format('|'.join(valid_aggregates)))
  54     patterns = [r'{field}',
  55                 r'{field}:{type}',
  56                 r'{aggregate}\({field}\)',
  57                 r'{aggregate}\({field}\):{type}']
  58     regexps = (re.compile('\A' + p.format(**units) + '\Z', re.DOTALL)
  59                for p in patterns[::-1])
  60 
  61     # find matches depending on valid fields passed
  62     match = next(exp.match(shorthand).groupdict() for exp in regexps
  63                  if exp.match(shorthand))
  64 
  65     # Use short form of the type expression
  66     typ = match.get('type', None)
  67     if typ:
  68         match['type'] = INV_TYPECODE_MAP.get(typ, typ)
  69     return match
  70 
  71 
  72 def construct_shorthand(field=None, aggregate=None, type=None):
  73     """Construct a shorthand representation.
  74 
  75     See also: parse_shorthand"""
  76     if field is None:
  77         return ''
  78 
  79     sh = field
  80 
  81     if aggregate is not None:
  82         sh = '{0}({1})'.format(aggregate, sh)
  83 
  84     if type is not None:
  85         type = TYPECODE_MAP.get(type, type)
  86         if type not in TYPE_ABBR:
  87             raise ValueError('Unrecognized Type: {0}'.format(type))
  88         sh = '{0}:{1}'.format(sh, type)
  89 
  90     return sh
  91 
  92 
  93 def infer_vegalite_type(data, field=None):
  94     """
  95     From an array-like input, infer the correct vega typecode
  96     ('ordinal', 'nominal', 'quantitative', or 'temporal')
  97 
  98     Parameters
  99     ----------
  100     data: Numpy array or Pandas Series
  101     field: str column name
  102     """
  103     # See if we can read the type from the field
  104     if field is not None:
  105         parsed = parse_shorthand(field)
  106         if parsed.get('type'):
  107             return parsed['type']
  108 
  109     # Otherwise, infer based on the dtype of the input
  110     typ = pd.lib.infer_dtype(data)
  111 
  112     # TODO: Once this returns 'O', please update test_select_x and test_select_y in test_api.py
  113 
  114     if typ in ['floating', 'mixed-integer-float', 'integer',
  115                'mixed-integer', 'complex']:
  116         return 'quantitative'
  117     elif typ in ['string', 'bytes', 'categorical', 'boolean', 'mixed', 'unicode']:
  118         return 'nominal'
  119     elif typ in ['datetime', 'datetime64', 'timedelta',
  120                  'timedelta64', 'date', 'time', 'period']:
  121         return 'temporal'
  122     else:
  123         warnings.warn("I don't know how to infer vegalite type from '{0}'.  "
  124                       "Defaulting to nominal.".format(typ))
  125         return 'nominal'
  126 
  127 
  128 def sanitize_dataframe(df):
  129     """Sanitize a DataFrame to prepare it for serialization.
  130 
  131     * Make a copy
  132     * Raise ValueError if it has a hierarchical index.
  133     * Convert categoricals to strings.
  134     * Convert np.int dtypes to Python int objects
  135     * Convert floats to objects and replace NaNs by None.
  136     * Convert DateTime dtypes into appropriate string representations
  137     """
  138     df = df.copy()
  139 
  140     if isinstance(df.index, pd.core.index.MultiIndex):
  141         raise ValueError('Hierarchical indices not supported')
  142     if isinstance(df.columns, pd.core.index.MultiIndex):
  143         raise ValueError('Hierarchical indices not supported')
  144 
  145     for col_name, dtype in df.dtypes.iteritems():
  146         if str(dtype) == 'category':
  147             # XXXX: work around bug in to_json for categorical types
  148             # https://github.com/pydata/pandas/issues/10778
  149             df[col_name] = df[col_name].astype(str)
  150         elif np.issubdtype(dtype, np.integer):
  151             # convert integers to objects; np.int is not JSON serializable
  152             df[col_name] = df[col_name].astype(object)
  153         elif np.issubdtype(dtype, np.floating):
  154             # For floats, convert nan->None: np.float is not JSON serializable
  155             col = df[col_name].astype(object)
  156             df[col_name] = col.where(col.notnull(), None)
  157         elif str(dtype).startswith('datetime'):
  158             # Convert datetimes to strings
  159             # astype(str) will choose the appropriate resolution
  160             df[col_name] = df[col_name].astype(str).replace('NaT', '')
  161     return df
  162
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/altair/utils/core.py b/altair/utils/core.py
  --- a/altair/utils/core.py
  +++ b/altair/utils/core.py
  @@ -142,6 +142,12 @@
       if isinstance(df.columns, pd.core.index.MultiIndex):
           raise ValueError('Hierarchical indices not supported')
   
  +    def to_list_if_array(val):
  +        if isinstance(val, np.ndarray):
  +            return val.tolist()
  +        else:
  +            return val
  +
       for col_name, dtype in df.dtypes.iteritems():
           if str(dtype) == 'category':
               # XXXX: work around bug in to_json for categorical types
  @@ -158,4 +164,9 @@
               # Convert datetimes to strings
               # astype(str) will choose the appropriate resolution
               df[col_name] = df[col_name].astype(str).replace('NaT', '')
  +        elif dtype == object:
  +            # Convert numpy arrays saved as objects to lists
  +            # Arrays are not JSON serializable
  +            col = df[col_name].apply(to_list_if_array, convert_dtype=False)
  +            df[col_name] = col.where(col.notnull(), None)
       return df
  
verification_info: {"golden_diff": "diff --git a/altair/utils/core.py b/altair/utils/core.py\n--- a/altair/utils/core.py\n+++ b/altair/utils/core.py\n@@ -142,6 +142,12 @@\n     if isinstance(df.columns, pd.core.index.MultiIndex):\n         raise ValueError('Hierarchical indices not supported')\n \n+    def to_list_if_array(val):\n+        if isinstance(val, np.ndarray):\n+            return val.tolist()\n+        else:\n+            return val\n+\n     for col_name, dtype in df.dtypes.iteritems():\n         if str(dtype) == 'category':\n             # XXXX: work around bug in to_json for categorical types\n@@ -158,4 +164,9 @@\n             # Convert datetimes to strings\n             # astype(str) will choose the appropriate resolution\n             df[col_name] = df[col_name].astype(str).replace('NaT', '')\n+        elif dtype == object:\n+            # Convert numpy arrays saved as objects to lists\n+            # Arrays are not JSON serializable\n+            col = df[col_name].apply(to_list_if_array, convert_dtype=False)\n+            df[col_name] = col.where(col.notnull(), None)\n     return df\n", "issue": "numpy scalar in Dataframe not JSON serializable\nIs it possible to allow numpy scalars in a dataframe?\n\nThe following code is not working, because a np.array is not json serializable:\n\n```\ndf_numpy = pd.DataFrame([dict(\n        x=np.array(1),\n        y=np.array(2),\n        )])\nChart(df_numpy).encode(x='x', y='y')\n# TypeError: array(1) is not JSON serializable\n```\n\nFull Example: [\nhttps://github.com/boeddeker/ipynb/blob/master/bug_altair_numpy.ipynb](https://github.com/boeddeker/ipynb/blob/master/bug_altair_numpy.ipynb)\n\n", "before_files": [{"content": "\"\"\"\nUtility routines\n\"\"\"\nimport re\nimport warnings\n\nimport pandas as pd\nimport numpy as np\n\n\nTYPECODE_MAP = {'ordinal': 'O',\n                'nominal': 'N',\n                'quantitative': 'Q',\n                'temporal': 'T'}\n\nINV_TYPECODE_MAP = {v: k for k, v in TYPECODE_MAP.items()}\n\nTYPE_ABBR = TYPECODE_MAP.values()\n\n\ndef parse_shorthand(shorthand):\n    \"\"\"\n    Parse the shorthand expression for aggregation, field, and type.\n\n    These are of the form:\n\n    - \"col_name\"\n    - \"col_name:O\"\n    - \"average(col_name)\"\n    - \"average(col_name):O\"\n\n    Parameters\n    ----------\n    shorthand: str\n        Shorthand string\n\n    Returns\n    -------\n    D : dict\n        Dictionary containing the field, aggregate, and typecode\n    \"\"\"\n    if not shorthand:\n        return {}\n\n    # Must import this here to avoid circular imports\n    from ..schema import AggregateOp\n    valid_aggregates = AggregateOp().values\n    valid_typecodes = list(TYPECODE_MAP) + list(INV_TYPECODE_MAP)\n\n    # build regular expressions\n    units = dict(field='(?P<field>.*)',\n                 type='(?P<type>{0})'.format('|'.join(valid_typecodes)),\n                 aggregate='(?P<aggregate>{0})'.format('|'.join(valid_aggregates)))\n    patterns = [r'{field}',\n                r'{field}:{type}',\n                r'{aggregate}\\({field}\\)',\n                r'{aggregate}\\({field}\\):{type}']\n    regexps = (re.compile('\\A' + p.format(**units) + '\\Z', re.DOTALL)\n               for p in patterns[::-1])\n\n    # find matches depending on valid fields passed\n    match = next(exp.match(shorthand).groupdict() for exp in regexps\n                 if exp.match(shorthand))\n\n    # Use short form of the type expression\n    typ = match.get('type', None)\n    if typ:\n        match['type'] = INV_TYPECODE_MAP.get(typ, typ)\n    return match\n\n\ndef construct_shorthand(field=None, aggregate=None, type=None):\n    \"\"\"Construct a shorthand representation.\n\n    See also: parse_shorthand\"\"\"\n    if field is None:\n        return ''\n\n    sh = field\n\n    if aggregate is not None:\n        sh = '{0}({1})'.format(aggregate, sh)\n\n    if type is not None:\n        type = TYPECODE_MAP.get(type, type)\n        if type not in TYPE_ABBR:\n            raise ValueError('Unrecognized Type: {0}'.format(type))\n        sh = '{0}:{1}'.format(sh, type)\n\n    return sh\n\n\ndef infer_vegalite_type(data, field=None):\n    \"\"\"\n    From an array-like input, infer the correct vega typecode\n    ('ordinal', 'nominal', 'quantitative', or 'temporal')\n\n    Parameters\n    ----------\n    data: Numpy array or Pandas Series\n    field: str column name\n    \"\"\"\n    # See if we can read the type from the field\n    if field is not None:\n        parsed = parse_shorthand(field)\n        if parsed.get('type'):\n            return parsed['type']\n\n    # Otherwise, infer based on the dtype of the input\n    typ = pd.lib.infer_dtype(data)\n\n    # TODO: Once this returns 'O', please update test_select_x and test_select_y in test_api.py\n\n    if typ in ['floating', 'mixed-integer-float', 'integer',\n               'mixed-integer', 'complex']:\n        return 'quantitative'\n    elif typ in ['string', 'bytes', 'categorical', 'boolean', 'mixed', 'unicode']:\n        return 'nominal'\n    elif typ in ['datetime', 'datetime64', 'timedelta',\n                 'timedelta64', 'date', 'time', 'period']:\n        return 'temporal'\n    else:\n        warnings.warn(\"I don't know how to infer vegalite type from '{0}'.  \"\n                      \"Defaulting to nominal.\".format(typ))\n        return 'nominal'\n\n\ndef sanitize_dataframe(df):\n    \"\"\"Sanitize a DataFrame to prepare it for serialization.\n\n    * Make a copy\n    * Raise ValueError if it has a hierarchical index.\n    * Convert categoricals to strings.\n    * Convert np.int dtypes to Python int objects\n    * Convert floats to objects and replace NaNs by None.\n    * Convert DateTime dtypes into appropriate string representations\n    \"\"\"\n    df = df.copy()\n\n    if isinstance(df.index, pd.core.index.MultiIndex):\n        raise ValueError('Hierarchical indices not supported')\n    if isinstance(df.columns, pd.core.index.MultiIndex):\n        raise ValueError('Hierarchical indices not supported')\n\n    for col_name, dtype in df.dtypes.iteritems():\n        if str(dtype) == 'category':\n            # XXXX: work around bug in to_json for categorical types\n            # https://github.com/pydata/pandas/issues/10778\n            df[col_name] = df[col_name].astype(str)\n        elif np.issubdtype(dtype, np.integer):\n            # convert integers to objects; np.int is not JSON serializable\n            df[col_name] = df[col_name].astype(object)\n        elif np.issubdtype(dtype, np.floating):\n            # For floats, convert nan->None: np.float is not JSON serializable\n            col = df[col_name].astype(object)\n            df[col_name] = col.where(col.notnull(), None)\n        elif str(dtype).startswith('datetime'):\n            # Convert datetimes to strings\n            # astype(str) will choose the appropriate resolution\n            df[col_name] = df[col_name].astype(str).replace('NaT', '')\n    return df\n", "path": "altair/utils/core.py"}], "after_files": [{"content": "\"\"\"\nUtility routines\n\"\"\"\nimport re\nimport warnings\n\nimport pandas as pd\nimport numpy as np\n\n\nTYPECODE_MAP = {'ordinal': 'O',\n                'nominal': 'N',\n                'quantitative': 'Q',\n                'temporal': 'T'}\n\nINV_TYPECODE_MAP = {v: k for k, v in TYPECODE_MAP.items()}\n\nTYPE_ABBR = TYPECODE_MAP.values()\n\n\ndef parse_shorthand(shorthand):\n    \"\"\"\n    Parse the shorthand expression for aggregation, field, and type.\n\n    These are of the form:\n\n    - \"col_name\"\n    - \"col_name:O\"\n    - \"average(col_name)\"\n    - \"average(col_name):O\"\n\n    Parameters\n    ----------\n    shorthand: str\n        Shorthand string\n\n    Returns\n    -------\n    D : dict\n        Dictionary containing the field, aggregate, and typecode\n    \"\"\"\n    if not shorthand:\n        return {}\n\n    # Must import this here to avoid circular imports\n    from ..schema import AggregateOp\n    valid_aggregates = AggregateOp().values\n    valid_typecodes = list(TYPECODE_MAP) + list(INV_TYPECODE_MAP)\n\n    # build regular expressions\n    units = dict(field='(?P<field>.*)',\n                 type='(?P<type>{0})'.format('|'.join(valid_typecodes)),\n                 aggregate='(?P<aggregate>{0})'.format('|'.join(valid_aggregates)))\n    patterns = [r'{field}',\n                r'{field}:{type}',\n                r'{aggregate}\\({field}\\)',\n                r'{aggregate}\\({field}\\):{type}']\n    regexps = (re.compile('\\A' + p.format(**units) + '\\Z', re.DOTALL)\n               for p in patterns[::-1])\n\n    # find matches depending on valid fields passed\n    match = next(exp.match(shorthand).groupdict() for exp in regexps\n                 if exp.match(shorthand))\n\n    # Use short form of the type expression\n    typ = match.get('type', None)\n    if typ:\n        match['type'] = INV_TYPECODE_MAP.get(typ, typ)\n    return match\n\n\ndef construct_shorthand(field=None, aggregate=None, type=None):\n    \"\"\"Construct a shorthand representation.\n\n    See also: parse_shorthand\"\"\"\n    if field is None:\n        return ''\n\n    sh = field\n\n    if aggregate is not None:\n        sh = '{0}({1})'.format(aggregate, sh)\n\n    if type is not None:\n        type = TYPECODE_MAP.get(type, type)\n        if type not in TYPE_ABBR:\n            raise ValueError('Unrecognized Type: {0}'.format(type))\n        sh = '{0}:{1}'.format(sh, type)\n\n    return sh\n\n\ndef infer_vegalite_type(data, field=None):\n    \"\"\"\n    From an array-like input, infer the correct vega typecode\n    ('ordinal', 'nominal', 'quantitative', or 'temporal')\n\n    Parameters\n    ----------\n    data: Numpy array or Pandas Series\n    field: str column name\n    \"\"\"\n    # See if we can read the type from the field\n    if field is not None:\n        parsed = parse_shorthand(field)\n        if parsed.get('type'):\n            return parsed['type']\n\n    # Otherwise, infer based on the dtype of the input\n    typ = pd.lib.infer_dtype(data)\n\n    # TODO: Once this returns 'O', please update test_select_x and test_select_y in test_api.py\n\n    if typ in ['floating', 'mixed-integer-float', 'integer',\n               'mixed-integer', 'complex']:\n        return 'quantitative'\n    elif typ in ['string', 'bytes', 'categorical', 'boolean', 'mixed', 'unicode']:\n        return 'nominal'\n    elif typ in ['datetime', 'datetime64', 'timedelta',\n                 'timedelta64', 'date', 'time', 'period']:\n        return 'temporal'\n    else:\n        warnings.warn(\"I don't know how to infer vegalite type from '{0}'.  \"\n                      \"Defaulting to nominal.\".format(typ))\n        return 'nominal'\n\n\ndef sanitize_dataframe(df):\n    \"\"\"Sanitize a DataFrame to prepare it for serialization.\n\n    * Make a copy\n    * Raise ValueError if it has a hierarchical index.\n    * Convert categoricals to strings.\n    * Convert np.int dtypes to Python int objects\n    * Convert floats to objects and replace NaNs by None.\n    * Convert DateTime dtypes into appropriate string representations\n    \"\"\"\n    df = df.copy()\n\n    if isinstance(df.index, pd.core.index.MultiIndex):\n        raise ValueError('Hierarchical indices not supported')\n    if isinstance(df.columns, pd.core.index.MultiIndex):\n        raise ValueError('Hierarchical indices not supported')\n\n    def to_list_if_array(val):\n        if isinstance(val, np.ndarray):\n            return val.tolist()\n        else:\n            return val\n\n    for col_name, dtype in df.dtypes.iteritems():\n        if str(dtype) == 'category':\n            # XXXX: work around bug in to_json for categorical types\n            # https://github.com/pydata/pandas/issues/10778\n            df[col_name] = df[col_name].astype(str)\n        elif np.issubdtype(dtype, np.integer):\n            # convert integers to objects; np.int is not JSON serializable\n            df[col_name] = df[col_name].astype(object)\n        elif np.issubdtype(dtype, np.floating):\n            # For floats, convert nan->None: np.float is not JSON serializable\n            col = df[col_name].astype(object)\n            df[col_name] = col.where(col.notnull(), None)\n        elif str(dtype).startswith('datetime'):\n            # Convert datetimes to strings\n            # astype(str) will choose the appropriate resolution\n            df[col_name] = df[col_name].astype(str).replace('NaT', '')\n        elif dtype == object:\n            # Convert numpy arrays saved as objects to lists\n            # Arrays are not JSON serializable\n            col = df[col_name].apply(to_list_if_array, convert_dtype=False)\n            df[col_name] = col.where(col.notnull(), None)\n    return df\n", "path": "altair/utils/core.py"}]}