Разбить один столбец JSON в numpy на массив из нескольких столбцов - PullRequest
0 голосов
/ 15 февраля 2019

Я использую Elastic Search и после запроса получаю результат.С помощью 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 довольно быстро, если есть способ разделить этот JSON на 3 столбца по самой numpy во время инициализации массива, это будет намного быстрее для большого набора данных.

Так что яможно получить доступ к данным, например, по столбцам:

data[:, 'doc_count']

Облегчение доступа к отдельным столбцам.

Обратите внимание, я хочу избежать цикла python, чтобы сделать это.Уже сделали с пандами.Я хочу знать, может ли numpy делать это своими собственными внутренними функциями.

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

Хотя 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)

Или для преобразования строк в datetime

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)

Панды не выглядят так плохо!

0 голосов
/ 15 февраля 2019

вам нужно манипулировать вашими данными, чтобы получить матричное представление вашей таблицы / 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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...