Skip to content

Moving pandasjson back into mainline pandas #3583

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions LICENSES/ULTRAJSON_LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the ESN Social Software AB nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
http://code.google.com/p/stringencoders/
Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.

Numeric decoder derived from from TCL library
http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
* Copyright (c) 1988-1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
112 changes: 106 additions & 6 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -1659,8 +1659,8 @@ def convert_objects(self, convert_dates=True, convert_numeric=False, copy=True):
-------
converted : DataFrame
"""
return self._constructor(self._data.convert(convert_dates=convert_dates,
convert_numeric=convert_numeric,
return self._constructor(self._data.convert(convert_dates=convert_dates,
convert_numeric=convert_numeric,
copy=copy))

#----------------------------------------------------------------------
Expand Down Expand Up @@ -3321,7 +3321,7 @@ def fillna(self, value=None, method=None, axis=0, inplace=False,
a reference to the filled object, which is self if inplace=True
limit : int, default None
Maximum size gap to forward or backward fill
downcast : dict, default is None, a dict of item->dtype of what to
downcast : dict, default is None, a dict of item->dtype of what to
downcast if possible

See also
Expand Down Expand Up @@ -3368,7 +3368,7 @@ def fillna(self, value=None, method=None, axis=0, inplace=False,
result[k].fillna(v, inplace=True)
return result
else:
new_data = self._data.fillna(value, inplace=inplace,
new_data = self._data.fillna(value, inplace=inplace,
downcast=downcast)

if inplace:
Expand Down Expand Up @@ -3756,8 +3756,8 @@ def combine(self, other, func, fill_value=None, overwrite=True):
result[col] = arr

# convert_objects just in case
return self._constructor(result,
index=new_index,
return self._constructor(result,
index=new_index,
columns=new_columns).convert_objects(copy=False)

def combine_first(self, other):
Expand Down Expand Up @@ -5278,6 +5278,106 @@ def mask(self, cond):
"""
return self.where(~cond, NA)


@classmethod
def from_json(cls, json, orient="columns", dtype=None, numpy=True):
"""
Convert JSON string to DataFrame

Parameters
----------
json : The JSON string to parse.
orient : {'split', 'records', 'index', 'columns', 'values'},
default 'columns'
The format of the JSON string
split : dict like
{index -> [index], columns -> [columns], data -> [values]}
records : list like [{column -> value}, ... , {column -> value}]
index : dict like {index -> {column -> value}}
columns : dict like {column -> {index -> value}}
values : just the values array
dtype : dtype of the resulting DataFrame
nupmpy: direct decoding to numpy arrays. default True but falls back
to standard decoding if a problem occurs.

Returns
-------
result : DataFrame
"""
from pandas.json import loads

df = None

if dtype is not None and orient == "split":
numpy = False

if numpy:
try:
if orient == "columns":
args = loads(json, dtype=dtype, numpy=True, labelled=True)
if args:
args = (args[0].T, args[2], args[1])
df = DataFrame(*args)
elif orient == "split":
decoded = loads(json, dtype=dtype, numpy=True)
decoded = dict((str(k), v) for k, v in decoded.iteritems())
df = DataFrame(**decoded)
elif orient == "values":
df = DataFrame(loads(json, dtype=dtype, numpy=True))
else:
df = DataFrame(*loads(json, dtype=dtype, numpy=True,
labelled=True))
except ValueError:
numpy = False
if not numpy:
if orient == "columns":
df = DataFrame(loads(json), dtype=dtype)
elif orient == "split":
decoded = dict((str(k), v)
for k, v in loads(json).iteritems())
df = DataFrame(dtype=dtype, **decoded)
elif orient == "index":
df = DataFrame(loads(json), dtype=dtype).T
else:
df = DataFrame(loads(json), dtype=dtype)

return df
DataFrame.from_json = from_json


def to_json(self, orient="columns", double_precision=10,
force_ascii=True):
"""
Convert DataFrame to a JSON string.

Note NaN's and None will be converted to null and datetime objects
will be converted to UNIX timestamps.

Parameters
----------
orient : {'split', 'records', 'index', 'columns', 'values'},
default 'columns'
The format of the JSON string
split : dict like
{index -> [index], columns -> [columns], data -> [values]}
records : list like [{column -> value}, ... , {column -> value}]
index : dict like {index -> {column -> value}}
columns : dict like {column -> {index -> value}}
values : just the values array
double_precision : The number of decimal places to use when encoding
floating point values, default 10.
force_ascii : force encoded string to be ASCII, default True.

Returns
-------
result : JSON compatible string
"""
from pandas.json import dumps
return dumps(self, orient=orient, double_precision=double_precision,
ensure_ascii=force_ascii)
DataFrame.to_json = to_json


_EMPTY_SERIES = Series([])


Expand Down
84 changes: 83 additions & 1 deletion pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -1962,7 +1962,7 @@ def dot(self, other):

Parameters
----------
other : Series or DataFrame
other : Series or DataFrame

Returns
-------
Expand Down Expand Up @@ -3241,6 +3241,88 @@ def str(self):
from pandas.core.strings import StringMethods
return StringMethods(self)


@classmethod
def from_json(cls, json, orient="index", dtype=None, numpy=True):
"""
Convert JSON string to Series

Parameters
----------
json : The JSON string to parse.
orient : {'split', 'records', 'index'}, default 'index'
The format of the JSON string
split : dict like
{index -> [index], name -> name, data -> [values]}
records : list like [value, ... , value]
index : dict like {index -> value}
dtype : dtype of the resulting Series
nupmpy: direct decoding to numpy arrays. default True but falls back
to standard decoding if a problem occurs.

Returns
-------
result : Series
"""
from pandas.json import loads
s = None

if dtype is not None and orient == "split":
numpy = False

if numpy:
try:
if orient == "split":
decoded = loads(json, dtype=dtype, numpy=True)
decoded = dict((str(k), v) for k, v in decoded.iteritems())
s = Series(**decoded)
elif orient == "columns" or orient == "index":
s = Series(*loads(json, dtype=dtype, numpy=True,
labelled=True))
else:
s = Series(loads(json, dtype=dtype, numpy=True))
except ValueError:
numpy = False
if not numpy:
if orient == "split":
decoded = dict((str(k), v)
for k, v in loads(json).iteritems())
s = Series(dtype=dtype, **decoded)
else:
s = Series(loads(json), dtype=dtype)

return s
Series.from_json = from_json

def to_json(self, orient="index", double_precision=10, force_ascii=True):
"""
Convert Series to a JSON string

Note NaN's and None will be converted to null and datetime objects
will be converted to UNIX timestamps.

Parameters
----------
orient : {'split', 'records', 'index'}, default 'index'
The format of the JSON string
split : dict like
{index -> [index], name -> name, data -> [values]}
records : list like [value, ... , value]
index : dict like {index -> value}
double_precision : The number of decimal places to use when encoding
floating point values, default 10.
force_ascii : force encoded string to be ASCII, default True.

Returns
-------
result : JSON compatible string
"""
from pandas.json import dumps
return dumps(self, orient=orient, double_precision=double_precision,
ensure_ascii=force_ascii)
Series.to_json = to_json


_INDEX_TYPES = ndarray, Index, list, tuple

#------------------------------------------------------------------------------
Expand Down
Loading