Вложенный json, содержащий список json-строк для фрейма данных

#json #python-3.x #pandas #dataframe

Вопрос:

У меня есть следующая json строка, которую я хотел бы поместить в фрейм данных:

 jsonstr = {
  "id": "12345",
  "ename": "A4.txt",
  "Zoom1": {
    "Zoom1_res": [
      {
        "code": "A1",
        "x": 3211,
        "y": 677,
        "part": "11",
        "lace": "29",
        "name": "COVER"
      },
      {
        "code": "A4",
        "x": 3492,
        "y": 1109,
        "part": "10",
        "lace": "19",
        "name": "ARMOUR"
      }
    ]
  },
  "iSize": {
    "width": 4608,
    "height": 3456
  },
  "Action": {
    "AA": {
      "detect": [
        {
          "class": "aa",
          "prob": 0.92,
          "Box": {
            "x0": 4406,
            "y0": 670,
            "x1": 4558,
            "y1": 760
          }
        },
        {
          "class": "aa",
          "prob": 0.92,
          "Box": {
            "x0": 3762,
            "y0": 655,
            "x1": 3913,
            "y1": 747
          }
        }
      ]
    }
  }
}
 

Используя json_read следующим образом:

 df =pd.read_json(jsonstr)
 

ВОЗВРАТ

  id   ename                                              Zoom1  
Zoom1_res  12345  A4.txt  [{'code': 'A1', 'x': 3211, 'y': 677, 'part': '...   
width      12345  A4.txt                                                NaN   
height     12345  A4.txt                                                NaN   
AA         12345  A4.txt                                                NaN   

            iSize                                             Action  
Zoom1_res     NaN                                                NaN  
width      4608.0                                                NaN  
height     3456.0                                                NaN  
AA            NaN  {'detect': [{'class': 'aa', 'prob': 0.92, 'Box...  
 

и

 pd.json_normalize(df['Action'])
 

возвращает ошибку

 AttributeError: 'float' object has no attribute 'values'
 

Итак, я подумал, что применение

 from ast import literal_eval

pd.json_normalize(df['Action'].apply(lambda x: literal_eval(x)["detect"]).explode())
 

возможно, это решит проблему, но они есть nan в этой колонке, так что даже это не работает.

Чего я на самом деле хочу, так это:

В лучшем из всех миров: id, ename, code, x, y, x0, y0, x1, y1

Все остальные данные не имеют для меня никакой ценности.

Благодарен за любую информацию!

Ответ №1:

Смотрите, что ваш JSON вложен на нескольких уровнях,

1. Создание субкадров данных

 df1 = pd.json_normalize(jsonstr, record_path=['Action','AA','detect'],  meta=['id','ename'])
df2 = pd.json_normalize(jsonstr, record_path=['Zoom1','Zoom1_res'],  meta=['id','ename'])
 

2. Перенос данных в NaN

Насколько я понимаю, gBOX и BOX-это одни и те же атрибуты, поэтому вы можете объединить их таким образом, ну, вы можете поиграть с ними и получить необходимые данные

 df3 = df1.apply(lambda x: pd.Series(x.dropna().values), axis=1)
df3.columns = ['class','prob','x0','y0','x1','y1','id','ename']
 

3. Получите необходимые столбцы в соответствии с вашими данными

 df4 = pd.merge(df3, df2, on=['id','ename'])
df4 = df4.iloc[:,[6,7,8,9,10,2,3,4,5]]
 

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

1. Это действительно очень мило! Однако один комментарий: , left_index=True, right_index=True для меня это не работает. Спасибо!