将numpy中的单列JSON拆分为多列数组

问题描述 投票:0回答:2

我正在使用弹性搜索,在查询之后,我得到了一个结果。使用Pandas,我能够将生成的JSON拆分为列,因此我可以对任何单个列执行任何操作。

我想和numpy一样。但如果我使用numpy,我只能实现单列JSON。

data = np.array(result_dict['aggregations']['date']['buckets'])


array([{u'key_as_string': u'2019-01-16T00:00:00.000+05:30', u'key': 1547577000000, u'doc_count': 1},
       {u'key_as_string': u'2019-01-17T00:00:00.000+05:30', u'key': 1547663400000, u'doc_count': 3},
       {u'key_as_string': u'2019-01-18T00:00:00.000+05:30', u'key': 1547749800000, u'doc_count': 3},
       {u'key_as_string': u'2019-01-19T00:00:00.000+05:30', u'key': 1547836200000, u'doc_count': 3}],
      dtype=object)

问题是,在这种情况下,如果我必须访问doc_count值,我必须再写一行代码。知道numpy非常快,如果有一种方法可以在初始化数组时通过numpy本身对这个JSON进行3列拆分,那么对于大型数据集来说会快得多。

这样我可以通过列来访问数据:

data[:, 'doc_count']

轻松访问各列。

请注意,我想避免python循环来做到这一点。已经完成了Pandas。我想知道numpy是否可以通过自己的内部函数来实现。

python json numpy
2个回答
0
投票

你必须操纵你的数据来获得你的表/ json的矩阵表示,你可以尝试:

import numpy as np


r = np.array([{'key_as_string': '2019-01-16T00:00:00.000+05:30', 'key': 1547577000000, 'doc_count': 1},
       {'key_as_string': '2019-01-17T00:00:00.000+05:30', 'key': 1547663400000, 'doc_count': 3},
       {'key_as_string': '2019-01-18T00:00:00.000+05:30', 'key': 1547749800000, 'doc_count': 3},
       {'key_as_string': '2019-01-19T00:00:00.000+05:30', 'key': 1547836200000, 'doc_count': 3}],
      dtype=object)

header = r[0].keys()
rows = np.append([list(header)],  [[e[h] for h in header] for e in  r] , axis=0)

print(rows)
# array([['key_as_string', 'key', 'doc_count'],
#        ['2019-01-16T00:00:00.000+05:30', '1547577000000', '1'],
#        ['2019-01-17T00:00:00.000+05:30', '1547663400000', '3'],
#        ['2019-01-18T00:00:00.000+05:30', '1547749800000', '3'],
#        ['2019-01-19T00:00:00.000+05:30', '1547836200000', '3']],
#       dtype='<U29')

rows[:, 2]
# array(['doc_count', '1', '3', '3', '3'], dtype='<U29')

如果您不想在列中包含标题:

header = list(r[0].keys())
rows = np.array([[e[h] for h in header] for e in  r])

print(rows)
#array([['2019-01-16T00:00:00.000+05:30', '1547577000000', '1'],
#       ['2019-01-17T00:00:00.000+05:30', '1547663400000', '3'],
#       ['2019-01-18T00:00:00.000+05:30', '1547749800000', '3'],
#       ['2019-01-19T00:00:00.000+05:30', '1547836200000', '3']],
#     dtype='<U29')
rows[:, header.index('doc_count')]
# array(['1', '3', '3', '3'], dtype='<U29')

0
投票

虽然pandas可以通过简单的调用从列表中创建数据帧,但这并不意味着它很快。

In [260]: alist =[{u'key_as_string': u'2019-01-16T00:00:00.000+05:30', u'key': 1
     ...: 547577000000, u'doc_count': 1},
     ...:        {u'key_as_string': u'2019-01-17T00:00:00.000+05:30', u'key': 15
     ...: 47663400000, u'doc_count': 3},
     ...:        {u'key_as_string': u'2019-01-18T00:00:00.000+05:30', u'key': 15
     ...: 47749800000, u'doc_count': 3},
     ...:        {u'key_as_string': u'2019-01-19T00:00:00.000+05:30', u'key': 15
     ...: 47836200000, u'doc_count': 3}]
     ...:        
In [261]: pd.DataFrame(alist)
Out[261]: 
   doc_count              ...                                key_as_string
0          1              ...                2019-01-16T00:00:00.000+05:30
1          3              ...                2019-01-17T00:00:00.000+05:30
2          3              ...                2019-01-18T00:00:00.000+05:30
3          3              ...                2019-01-19T00:00:00.000+05:30

[4 rows x 3 columns]
In [262]: _.dtypes
Out[262]: 
doc_count         int64
key               int64
key_as_string    object
dtype: object
In [263]: timeit pd.DataFrame(alist)
694 µs ± 19.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

在我的评论中,我专注于按键访问字典键,但忘记了我们可以快速访问所有值作为列表。

In [264]: [tuple(d.values()) for d in alist]
Out[264]: 
[('2019-01-16T00:00:00.000+05:30', 1547577000000, 1),
 ('2019-01-17T00:00:00.000+05:30', 1547663400000, 3),
 ('2019-01-18T00:00:00.000+05:30', 1547749800000, 3),
 ('2019-01-19T00:00:00.000+05:30', 1547836200000, 3)]
In [265]: timeit [tuple(d.values()) for d in alist]
1.43 µs ± 11.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

pandas相比,这是非常快的。

我使用tuple所以这个列表可以传递给结构化数组:

In [266]: dt = np.dtype([('key_as_string', 'U40'),('doc_count', int),('id',int)]
     ...: )
In [267]: np.array([tuple(d.values()) for d in alist],dt)
Out[267]: 
array([('2019-01-16T00:00:00.000+05:30', 1547577000000, 1),
       ('2019-01-17T00:00:00.000+05:30', 1547663400000, 3),
       ('2019-01-18T00:00:00.000+05:30', 1547749800000, 3),
       ('2019-01-19T00:00:00.000+05:30', 1547836200000, 3)],
      dtype=[('key_as_string', '<U40'), ('doc_count', '<i8'), ('id', '<i8')])
In [268]: timeit np.array([tuple(d.values()) for d in alist],dt)
5.12 µs ± 34.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

或者将字符串转换为日期时间

In [269]: dt1 = np.dtype([('key_as_string', 'datetime64[m]'),('doc_count', int),
     ...: ('id',int)])
In [270]: np.array([tuple(d.values()) for d in alist],dt1)
/usr/local/bin/ipython3:1: DeprecationWarning: parsing timezone aware datetimes is deprecated; this will raise an error in the future
  #!/usr/bin/python3
Out[270]: 
array([('2019-01-15T18:30', 1547577000000, 1),
       ('2019-01-16T18:30', 1547663400000, 3),
       ('2019-01-17T18:30', 1547749800000, 3),
       ('2019-01-18T18:30', 1547836200000, 3)],
      dtype=[('key_as_string', '<M8[m]'), ('doc_count', '<i8'), ('id', '<i8')])

这有点慢,但熊猫的速度要快得多。

并且只需访问字典中的一个键:

In [273]: [d['doc_count'] for d in alist]
Out[273]: [1, 3, 3, 3]
In [274]: np.array([d['doc_count'] for d in alist])
Out[274]: array([1, 3, 3, 3])
In [275]: timeit np.array([d['doc_count'] for d in alist])
2.69 µs ± 126 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

并让我们测试一个更大的列表:

In [308]: blist = alist * 1000
In [309]: timeit np.array([d['doc_count'] for d in blist])
430 µs ± 67.6 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [310]: timeit np.array([tuple(d.values()) for d in blist],dt)
2.18 ms ± 4.01 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [311]: timeit pd.DataFrame(blist)
5.6 ms ± 140 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

熊猫看起来不那么糟糕!

© www.soinside.com 2019 - 2024. All rights reserved.