Нормализуйте JSON, используя Python

1

Я относительно новичок в JSON и Python, и я изо всех сил пытаюсь сгладить JSON с двух последних дней. Я прочитал этот пример в http://pandas.pydata.org/pandas-docs/version/0.19/generated/pandas.io.json.json_normalize.html, но я не понял, как перечислить некоторые вложенные элементы. Я также прочитал несколько потоков Flatten JSON на основе атрибута - python Как нормализовать сложный вложенный json в python? и https://towardsdatascience.com/flattening-json-objects-in-python-f5343c794b10. Я пробовал все без везения.

Здесь первая запись моего файла JSON:

d = 
{'city': {'url': 'link',
  'name': ['San Francisco']},
 'rank': 1,
 'resident': [
  {'link': ['bit.ly/0842/'], 'name': ['John A']},
  {'link': ['bit.ly/5835/'], 'name': ['Tedd B']},
  {'link': ['bit.ly/2011/'], 'name': ['Cobb C']},
  {'link': ['bit.ly/0855/'], 'name': ['Jack N']},
  {'link': ['bit.ly/1430/'], 'name': ['Jack K']},
  {'link': ['bit.ly/3081/'], 'name': ['Edward']},
  {'link': ['bit.ly/2001/'], 'name': ['Jack W']},
  {'link': ['bit.ly/0020/'], 'name': ['Henry F']},
  {'link': ['bit.ly/2137/'], 'name': ['Joseph S']},
  {'link': ['bit.ly/3225/'], 'name': ['Ed B']},
  {'link': ['bit.ly/3667/'], 'name': ['George Vvec']},
  {'link': ['bit.ly/6434/'], 'name': ['Robert W']},
  {'link': ['bit.ly/4036/'], 'name': ['Rudy B']},
  {'link': ['bit.ly/6450/'], 'name': ['James K']},
  {'link': ['bit.ly/5180/'], 'name': ['Billy N']},
  {'link': ['bit.ly/7847/'], 'name': ['John S']}]
}

Здесь ожидаемый результат:

city_url  city_name      rank    resident_link   resident_name  
link      San Francisco   1     'bit.ly/0842/'   'John A'
link      San Francisco   1     'bit.ly/5835/'   'Tedd B'
link      San Francisco   1     'bit.ly/2011/'   'Cobb C'
link      San Francisco   1     'bit.ly/0855/'   'Jack N'
link      San Francisco   1     'bit.ly/1430/'   'Jack K'
link      San Francisco   1     'bit.ly/3081/'   'Edward'
link      San Francisco   1     'bit.ly/2001/'   'Jack W'
link      San Francisco   1     'bit.ly/0020/'   'Henry F'
link      San Francisco   1     'bit.ly/2137/'   'Joseph S'
link      San Francisco   1     'bit.ly/3225/'   'Ed B'
link      San Francisco   1     'bit.ly/3667/'   'George Vvec'
link      San Francisco   1     'bit.ly/6434/'   'Robert W'
link      San Francisco   1     'bit.ly/4036/'   'Rudy B'
link      San Francisco   1     'bit.ly/6450/'   'James K'
link      San Francisco   1     'bit.ly/5180/'   'Billy N'
link      San Francisco   1     'bit.ly/7847/'   'John S'

Функция flatten_json() (от Medium.com выше) разрушает иерархию. Вот несколько первых строк:

{'city_url': 'link',
 'city_name_0': 'San Francisco',
 'rank': 1,
 'resident_0_link_0': 'bit.ly/0842/',
 'resident_0_name_0': 'John A', ...

Может кто-то, пожалуйста, помогите мне, как думать о преобразовании этих наборов данных? К сожалению, документация pandas не дает никаких указаний начинающим. О, с чем я играл. Ничего не получилось.

from pandas.io.json import json_normalize
json_normalize(d,['city',['name','rank']])
json_normalize(d,['city','name','rank'])
json_normalize(d,['city','name'])

Я был бы признателен, если бы кто-нибудь рассказал, как сделать такой тип конверсии и мыслительный процесс.

Кроме того, я ищу векторную операцию или операцию O(N) а не O(N2) из-за количества данных в исходном наборе данных. Следовательно, что-либо медленнее, чем O(N), не будет работать.

Теги:
pandas
normalization

1 ответ

0

Если вы знаете структуру json blob, это сделает это

resident_link = [k['link'][0] for k in d['resident']]
resident_name = [k['name'][0] for k in d['resident']]
n = len(d['resident'])
city_url = n * [d['city']['url']]
city_name = n * [d['city']['name'][0]]
rank = n * [d['rank']]

df = pandas.DataFrame({
    'resident_name' : resident_name,
    'resident_link' : resident_link,
    'city_url' : city_url,
    'city_name' : city_name,
    'rank' : rank
})

Что производит

        city_name city_url  rank resident_link resident_name
0   San Francisco     link     1  bit.ly/0842/        John A
1   San Francisco     link     1  bit.ly/5835/        Tedd B
2   San Francisco     link     1  bit.ly/2011/        Cobb C
3   San Francisco     link     1  bit.ly/0855/        Jack N
4   San Francisco     link     1  bit.ly/1430/        Jack K
5   San Francisco     link     1  bit.ly/3081/        Edward
6   San Francisco     link     1  bit.ly/2001/        Jack W
7   San Francisco     link     1  bit.ly/0020/       Henry F
8   San Francisco     link     1  bit.ly/2137/      Joseph S
9   San Francisco     link     1  bit.ly/3225/          Ed B
10  San Francisco     link     1  bit.ly/3667/   George Vvec
11  San Francisco     link     1  bit.ly/6434/      Robert W
12  San Francisco     link     1  bit.ly/4036/        Rudy B
13  San Francisco     link     1  bit.ly/6450/       James K
14  San Francisco     link     1  bit.ly/5180/       Billy N
15  San Francisco     link     1  bit.ly/7847/        John S

РЕДАКТИРОВАТЬ

Как говорит OP в комментариях, представьте себе много таких записей, каждый из которых имеет ту же структуру

nrecords = 10
dd = {k : d for k in range(nrecords)}

dd теперь имеет 10 копий оригинальной json blob. И вот как код должен быть обновлен

ff = pandas.DataFrame()

for record in range(nrecords):

    n = len(dd[record]['resident'])

    df = {
        'resident_link' : [k['link'][0] for k in dd[record]['resident']],
        'resident_name' : [k['name'][0] for k in dd[record]['resident']],
        'city_url' : n * [dd[record]['city']['url']],
        'city_name' : n * [dd[record]['city']['name'][0]],
        'rank' : n * [dd[record]['rank']]
        }

    df = pandas.DataFrame(df)
    ff = ff.append(df).reset_index(drop = True)

Ниже приведена оценка времени выполнения в зависимости от количества записей. На основе этого потребуется около 1 часа для завершения 1,5 миллиона записей

Изображение 174551

  • 0
    Спасибо за вашу помощь. Как я могу сделать это, скажем, для 10 записей? Можно предположить, что все 10 записей одинаковы. Должен ли я пройти через 10 записей? Исходный набор данных, который у меня есть, имеет ~ 1,5 млн записей. Я не смог опубликовать образец 10 записей из-за недостатка места. Надеюсь, ты сможешь мне помочь. rank означает nth запись.
  • 0
    @watchtower Да, повторите то же самое и используйте concat для объединения строк данных
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню