Однако некоторые из этих ключей/идентификаторов содержится во вложенных объектах JSON, которые находятся в отдельных ячейках. Например, один столбец содержит список диктовок, и каждый из этих диктовок содержит пару пар ключ:значение, представляющих метаданные тега ключ:значение для объекта в заданной строке кадра данных. Первая пара ключ:значение — это идентификатор, который ссылается на ключ тега в другой таблице, вторая пара ключ:значение содержит фактическое значение тега. Таким образом, конечная цель — извлечь эти теги ключ/значение и поместить значения в столбец, названный в честь ключа. И мне нужно сделать это для стольких тегов, сколько существует, число, которое меняется от одной строки к другой.
Если я нормализую json, этот список расширится. на столбцы в кадре данных, которые имеют числовые индексы (соответствующие списку).
Входящий JSON выглядит следующим образом:
Код: Выделить всё
deviceJSON = {
"devices": [
{
"name": "foo",
"noteIds": [],
"vendor": "Aruba",
"model": "2920F",
"tags": [],
"id": ,
},
{
"location": {
"floor": ,
"coord": {
"x": 100,
"y": 200
}
},
"name": "bar",
"noteIds": ["32b60e81-8f9d-4ea2-9af0-8e441d31649b"],
"vendor": "Cisco",
"model": "6500",
"tags": [
{
"tagKeyId": "68a9a2e4-9d03-42dd-8744-ed0d241f1746",
"value": "IDF 1"
},
{
"tagKeyId": "22a1adc4-bf73-4c52-a3f2-3bfca9d64011",
"value": "e-Waste"
}
],
"id": ,
}
]
}
deviceDF=pd.DataFrame(deviceJSON['devices'])
В конечном итоге мне нужно добраться до столбца с ключом тега либо как tag_keyname, либо просто keyname, а также значения в этом столбце (ключевое имя находится в другом Dataframe, индексированном tagKeyId):
Код: Выделить всё
tagKeysJSON = {
"tagKeys": [
{
"key": "IDF",
"id": "68a9a2e4-9d03-42dd-8744-ed0d241f1746",
},
{
"key": "Disposition",
"id": "22a1adc4-bf73-4c52-a3f2-3bfca9d64011",
}
]
}
tagKeysDF=pd.DataFrame(tagKeysJSON['tagKeys'])
Код: Выделить всё
deviceDF=deviceDF.join(pd.json_normalize(deviceDF.tags))
Столбец 0:
Код: Выделить всё
{"tagKeyId": "68a9a2e4-9d03-42dd-8744-ed0d241f1746","value": "IDF 1"}
Код: Выделить всё
{"tagKeyId": "22a1adc4-bf73-4c52-a3f2-3bfca9d64011","value": "e-Waste"}
Я уже делал это раньше, но это устарело и к тому же неэффективно:
Код: Выделить всё
tagsRawDF=deviceDF[['id','tags']]
tagsListDF=pd.DataFrame()
tagnameList=[]
for row in tagsRawDF.iterrows():
taglist=row[1][1]
df_dict={'deviceId' : row[1][0]}
for tag in row[1][1]:
tagrec=tagKeysDF.loc[tagKeysDF["id"]==tag['tagKeyId']]
tagname='tag_'+tagrec.key.values[0].replace(" ","_")
# Have we seen this tag name before?
# (this list is being built to be used later in the output phase)
if tagname not in tagnameList : tagnameList.append(tagname)
df_dict[tagname]=tag['value']
tmp_df = pd.DataFrame(df_dict, index=[0])
tagsListDF = tagsListDF._append(tmp_df) # append the tmp_df to our final df
tagsListDF.reset_index(drop=True)
deviceDF=pd.merge(deviceDF, tagsListDF, left_on='id', right_on='id',how='left')
FutureWarning: Series.getitem рассматривает ключи как позиции устарел. В будущей версии целочисленные ключи всегда будут рассматриваться как метки (в соответствии с поведением DataFrame). Чтобы получить доступ к значению по позиции, используйте ser.iloc[pos]
для тега в строке[1][1]:
Это странно специфично, но в то же время бесполезно, поскольку мне не удалось найти никакой хорошей документации, объясняющей, как провести рефакторинг кода для использования вместо него iloc.
Итак, Я немного застрял в том, как на самом деле подойти к этому - это было бы просто, если бы количество тегов было предсказуемым, но теперь это превышает мои ограниченные знания о Pandas (и хотя документация хороша, мне не поможет, если Я даже не знаю, что я на самом деле ищу).
Подробнее здесь: https://stackoverflow.com/questions/791 ... to-columns