flatten_json предоставляет мне длинный список столбцов и одну строку вместо требуемой структуры фрейма данных

#json #python-3.x #pandas #database #csv

#json #python-3.x #панды #База данных #csv

Вопрос:

Я конвертирую вложенный файл json, содержащий более 100 записей, в файл flattend csv. Пример файла json показан ниже:

 sampleJson = {
       'record1': 
              {
                'text':[   ['A', 'fried', 'is', 'a', 'nice', 'companion', '.'],  
                           ['The', 'birds', 'are', 'flying', '.']],                           
                'values':[ [0, 1, 0, 0],  
                           [1, 1, 0, 1]],
                'pairs':[  [0, 2],  
                           [2, 1]]
             },
  'record2': 
             {
                'text':[   ['We', 'can', 'work', 'hard', 'together', '.'], 
                           ['Let', 'the', 'things', 'happen', '.'], 
                           ['There', 'is', 'always', 'a', 'way', 'out', '.']],
              'values':[   [0, 1, 0, 0], 
                           [0, 1, 1, 1], 
                           [1, 1, 0, 1]],
               'pairs':[   [0, 2],  
                           [3, 4], 
                           [2, 1]]
             },
     ..... 100 records
       }
  

Структура csv, которую я хочу получить из этого вложенного json,:

   record1,    A friend is a nice companion.,    0, 1, 0, 0,      [0, 2]
         ,    The bids are flying.,             1, 1, 0, 1,      [2, 1]
  record2,    We can work hard together.,       0, 1, 0, 0,      [0, 2]
         ,    Let the things happen.,           0, 1, 1, 1,      [4, 3]
         ,    There is always a way out.,       1, 1, 0, 1,      [2, 1]
  record3, 
  ....... upto 100 records
  

Я использовал следующий код для выравнивания вложенного файла:

  def flatten_json(y):
   out = {}

   def flatten(x, name=''):
      if type(x) is dict:
        for a in x:
            flatten(x[a], name   a   '_')
      elif type(x) is list:
        i = 0
        for a in x:
            flatten(a, name   str(i)   '_')
            i  = 1
      else:
        out[name[:-1]] = x

   flatten(y)
   return out   

flatIt = flatten_json(sampleJson)
df= pd.json_normalize(flatIt) 
df.to_csv('outPutFile.csv', encoding='utf-8')
print(df)
  

Я получаю длинный список столбцов со структурой типа record1.text, record1.values, record1.pairs, record2.text и так далее с одной строкой, а также каждое слово предложений в тексте находится в отдельном столбце.

Я буду признателен за некоторую помощь. Спасибо..

Ответ №1:

Вы можете использовать этот пример для анализа Json в dataframe:

 import pandas as pd


sampleJson = {
       'record1': 
              {
                'text':[   ['A', 'fried', 'is', 'a', 'nice', 'companion', '.'],  
                           ['The', 'birds', 'are', 'flying', '.']],                           
                'values':[ [0, 1, 0, 0],  
                           [1, 1, 0, 1]],
                'pairs':[  [0, 2],  
                           [2, 1]]
             },
  'record2': 
             {
                'text':[   ['We', 'can', 'work', 'hard', 'together', '.'], 
                           ['Let', 'the', 'things', 'happen', '.'], 
                           ['There', 'is', 'always', 'a', 'way', 'out', '.']],
               'values':[   [0, 1, 0, 0], 
                           [0, 1, 1, 1], 
                           [1, 1, 0, 1]],
               'pairs':[   [0, 2],  
                           [3, 4], 
                           [2, 1]]
             },
       }

all_data = []
for k, v in sampleJson.items():
    texts, values, pairs = v['text'], v['values'], v['pairs']
    for t, val, p in zip(texts, values, pairs):
        all_data.append({
            'record': k,
            'text': ' '.join(t),
            'pairs': p,
            **{'val_{}'.format(i): val_ for i, val_ in enumerate(val, 1)}
        })

df = pd.DataFrame(all_data)
print(df)
  

Печатает этот фрейм данных:

     record                           text   pairs  val_1  val_2  val_3  val_4
0  record1  A fried is a nice companion .  [0, 2]      0      1      0      0
1  record1         The birds are flying .  [2, 1]      1      1      0      1
2  record2    We can work hard together .  [0, 2]      0      1      0      0
3  record2        Let the things happen .  [3, 4]      0      1      1      1
4  record2    There is always a way out .  [2, 1]      1      1      0      1
  

Комментарии:

1. Привет, Андрей, большое спасибо за помощь. Я действительно ценю это, поскольку я боролся с этим в течение недели. У меня просто есть несколько вопросов, чтобы лучше понять код, поскольку это шанс учиться (я очень плохо разбираюсь во вложенных структурах). Почему вы использовали zip во втором цикле? и если вместо текста, значений и столбцов пар есть разные числа. Например, в каждой записи на 2-м уровне у меня разные числа, скажем, 11, 23, 14 в первой записи и 12, 34 12 во второй записи и так далее с тем же содержимым. Было бы здорово, если бы вы могли немного помочь, если у вас есть время, в противном случае большое спасибо.

2. @codeDB я использовал zip() для «связывания» значений из 'text' 'values' и 'pairs' списков вместе. Каждый элемент из этих списков принадлежит одной строке.

3. Большое спасибо. Мне удалось решить второй вопрос, который я задал, о наличии чисел вместо текста, значений и пар.