合并许多json字符串与python pandas输入

时间:2015-01-21 22:35:36

标签: python json serialization pandas concat

摘要

我创建了由pandas个对象(如DataFramePanel组成的数据对象(包括其他内容)。我希望将这些对象序列化为json,速度是首要考虑因素。

使用pandas.Panel

的示例

比方说我有一个像这样的小组:

In [54]: panel = pandas.Panel( 
             numpy.random.randn(5, 100, 10), 
             items = ['a', 'b', 'c', 'd', 'e'], 
             major_axis = pandas.DatetimeIndex(start = '01/01/2000', 
                                               freq = 'b', 
                                               periods = 100
             ), 
             minor_axis = ['z', 'y', 'x', 'v', 'u', 't', 's', 'r', 'q', 'o']
          )
In [64]: panel
Out[64]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 5 (items) x 100 (major_axis) x 10 (minor_axis)
Items axis: a to e
Major_axis axis: 2000-01-03 00:00:00 to 2000-05-19 00:00:00
Minor_axis axis: z to o

我想将此panel变为扁平json

注意:我使用更复杂的对象执行此操作,但循环键和为每个键生成json数据的整体逻辑是相同的

我可以像这样写一个快速而肮脏的panel_to_json()函数:

def panel_to_json(panel):

    d = {'__type__' : 'panel'}
    for item in panel.items:
        tmp = panel.loc[item ,: , :].to_json()
        d[item] = eval(tmp)
    return json.dumps(d)

In [58]: tmp = panel_to_json(panel)
In [59]: tmp[:100]
Out[59]: '{"a": {"q": {"948931200000": -0.5586319118, "951955200000": 0.6820748888, "949363200000": -0.0153867'

这使我获得了正确的结果,问题是eval使用非常代价高昂。例如,如果我删除了eval,并且只处理\\函数产生的panel_no_eval_to_json的一小部分:

def panel_no_eval_to_json(panel):
    d = {'__type__' : 'panel'}
    for item in panel.items:
        d[item] = panel.loc[item ,: , :].to_json()
    return json.dumps(d)

In [60]: tmp = panel_no_eval_to_json(panel)

In [61]: tmp[:100]
Out[61]: '{"a": "{\\"z\\":{\\"946857600000\\":1.0233515965,\\"946944000000\\":-1.1333560575,\\"947030400000\\":-0.0072'

速度差异很大,检查他们的%timeit值!!:

In [62]: %timeit panel_no_eval_to_json(panel)
100 loops, best of 3: 3.55 ms per loop

In [63]: %timeit panel_to_json(panel)
10 loops, best of 3: 41.1 ms per loop

结束目标

所以我的最终目标是遍历Panel(或我的对象,它具有不同的键/属性,其中许多是Panel&{39}和DataFrame s),并将从调用json创建的to_json()流合并到聚合的json流(实际上是我的数据对象的展平数据表示),就像使用上面的panel_to_json功能( eval)。

我的主要目标是:

  1. 利用现有的pandas to_json功能
  2. 利用加速和现有的库(我可以编写自己的json_stream_merger,但显然已经完成了,对吧?)

3 个答案:

答案 0 :(得分:1)

最后,最快的方法是编写一个简单的字符串concat - 呃。以下是两个最佳解决方案(一个由@Skorp提供))和它们各自的%timeit次以图形形式

方法1.字符串合并

def panel_to_json_string(panel):
    def __merge_stream(key, stream):
        return '"' + key + '"' + ': ' + stream + ', '

    try:
        stream = '{ "__type__": "panel", '
        for item in panel.items:
            stream += __merge_stream(item, panel.loc[item, :, :].to_json()) 

        # take out extra last comma
        stream = stream[:-2] 

        # add the final paren
        stream += '}'
    except:
        logging.exception('Panel Encoding did not work')
return stream

方法2.加载 - 转储

def panel_to_json_loads(panel):
    try:
        d = {'__type__' : 'panel'}

        for item in panel.items:
            d[item] = json.loads(panel.loc[item ,: , :].to_json())
        return json.dumps(d)
    except:
        logging.exception('Panel Encoding did not work')

问题设置

import timeit
import pandas
import numpy

setup = ("import strat_check.io as sio; import pandas; import numpy;" 
     "panel = pandas.Panel(numpy.random.randn(5, {0}, 4), "
     "items = ['a', 'b', 'c', 'd', 'e'], " 
     "major_axis = pandas.DatetimeIndex(start = '01/01/1990',"
                                        "freq = 's', "
                                        "periods = {0}), "
                                        "minor_axis = numpy.arange(4))")

vals = [10, 100, 1000, 10000, 100000]

d = {'string-merge': [], 
     'loads-dumps': []
     }

for n in vals:
    number = 10

d['string-merge'].append(
    timeit.timeit(stmt = 'panel_to_json_string(panel)', 
                  setup = setup.format(n), 
                  number = number)
)

d['loads-dumps'].append(
    timeit.timeit(stmt = 'sio.panel_to_json_loads(panel)', 
                  setup = setup.format(n), 
                  number = number)
)

enter image description here

答案 1 :(得分:0)

如果你需要做的就是摆脱&#34; \\&#34;你可以使用
    .str.strip("\\") #or

`.str.replace("\\","") `

你应该阅读字符串方法,矢量化字符串方法和正则表达式。这里有大熊猫的具体信息链接:

http://pandas.pydata.org/pandas-docs/stable/text.html#text-string-methods

答案 2 :(得分:0)

您是否考虑过合并数据帧然后“to_json”那个帧?你可以使用pd.merge(masterdf,panel [item],how =“outer”)。只是一个想法,我没有使用面板,所以不确定json表示是否准确。您也可以尝试在循环中使用它。您还应该考虑使用iteritems()方法。

masterdf = pd.concat([masterdf, panel[item]], axis = 1, keys =[list(masterdf.columns.values), item]) and then make that into a json.  

你甚至可以做一些更性感的事情:

pd.concat([lamda x: x for panel.items], axis = 1, keys = list(panel.keys())).to_json