#python #pandas #dataframe
#python #pandas #фрейм данных
Вопрос:
Это список имеющихся у меня словарей, которые необходимо преобразовать в фрейм данных. Я пытался использовать мультииндекс, но не смог преобразовать весь фрейм данных.
response = [{
"name": "xyz",
"empId": "007",
"details": [{
"address": [{
"street": "x street",
"city": "x city"
}, {
"street": "xx street",
"city": "xx city"
}],
"country": "xxz country"
},
{
"address": [{
"street": "y street",
"city": "y city"
}, {
"street": "yy street",
"city": "yy city"
}],
"country": "yyz country"
}
]
}]
Мне удалось получить внутренний список словарей в фрейм данных с помощью следующего кода:
for i in details:
Country = i['country']
street =[]
city = []
index = pd.MultiIndex.from_arrays([[Country]*len(i['address']), list(range(1,len(i['address']) 1))], names=['Country', 'SL No'])
df=pd.DataFrame(columns=["Street","City"],index=index)
if i['address']:
for row in i['address']:
street.append(row['street'])
city.append(row['city'])
df["Street"]=street
df["City"]=city
frames.append(df)
df_final=pd.concat(frames)
Полученный результат:
Country SL No Street City
xxz country 1 x street x city
2 xx street xx city
yyz country 1 y street y city
2 yy street yy city
Как я могу преобразовать список словарей в фрейм данных, сохранив всю информацию?
Конечный результат, который я хочу:
Name EmpId Country Street City
xyz 007 xxz country x street x city
xx street xx city
yyz country y street y city
yy street yy cit
Комментарии:
1. не могли бы вы добавить конечный формат вывода, который вы хотите
2. @HadiMir добавили конечный результат, который мне требуется.
Ответ №1:
Использовать json_normalize
с DataFrame.set_index
:
df = pd.json_normalize(response,
record_path=['details','address'],
meta=['name','empId', ['address','country']]
)
df = df.set_index(['name','empId','address.country'])
print (df)
street city
name empId address.country
xyz 007 xxz country x street x city
xxz country xx street xx city
yyz country y street y city
yyz country yy street yy city
Для более старых версий pandas используйте:
df = pd.io.json.json_normalize(response,
record_path=['details','address'],
meta=['name','empId', ['address','country']]
)
Редактировать:
Протестировано с несколькими значениями и работает хорошо:
response = [{
"name": "xyz",
"empId": "007",
"details": [{
"address": [{
"street": "x street",
"city": "x city"
}, {
"street": "xx street",
"city": "xx city"
}],
"country": "xxz country"
},
{
"address": [{
"street": "y street",
"city": "y city"
}, {
"street": "yy street",
"city": "yy city"
}],
"country": "yyz country"
}
]
},
{
"name": "xyz1",
"empId": "0071",
"details": [{
"address": [{
"street": "x street1",
"city": "x city1"
}, {
"street": "xx stree1t",
"city": "xx city1"
}],
"country": "xxz country"
},
{
"address": [{
"street": "y street",
"city": "y city"
}, {
"street": "yy street",
"city": "yy city"
}],
"country": "yyz country"
}
]
}]
df = pd.json_normalize(response,
record_path=['details','address'],
meta=['name','empId', ['address','country']]
)
df = df.set_index(['name','empId','address.country'])
print (df)
street city
name empId address.country
xyz 007 xxz country x street x city
xxz country xx street xx city
yyz country y street y city
yyz country yy street yy city
xyz1 0071 xxz country x street1 x city1
xxz country xx stree1t xx city1
yyz country y street y city
yyz country yy street yy city
Комментарии:
1. Да. Это служит цели. Но что, если у меня есть большой набор данных в том же формате, он должен быть повторен.
2. @laplace — Не уверен, что повторяется? Существует много файлов json и нужно повторить мое решение?
3. @jezrael. Мой набор данных такой большой, что мне придется перебирать набор данных и преобразовывать весь набор данных в df. Ваше решение отлично работает для ответа [0], что делать, если у меня есть ответ [1 ….n] .
4. @jezrael Мой плохой. Это работает. Есть ли способ переименовать ‘address.country’ на другое имя?
5. @laplace Конечно, используйте
df. rename(columns='address.country' :'new')
передdf = df.set_index(['name','empId','address.country'])
Ответ №2:
Насколько я знаю, нет простого способа сделать это, поскольку ваши данные содержат несколько уровней списков. Хотя это немного запутанно, следующее должно работать. Код будет итеративно explode
перечислять и преобразовывать словари в столбцы с json_normalize
помощью .
df = pd.DataFrame.from_records(response)
df = df.explode('details', ignore_index=True)
df = pd.concat([df, pd.json_normalize(df['details'])], axis=1)
df = df.explode('address', ignore_index=True)
df = pd.concat([df, pd.json_normalize(df['address'])], axis=1)
df = df.drop(columns=['details', 'address'])
Результат:
name empId country street city
0 xyz 007 xxz country x street x city
1 xyz 007 xxz country xx street xx city
2 xyz 007 yyz country y street y city
3 xyz 007 yyz country yy street yy city
Примечание: для версий pandas старше 1.1.0 explode
ignore_index
параметр отсутствует. Вместо этого используйте reset_index(drop=True)
после explode
.
Кроме того, в более старых версиях pandas вам нужно использовать pd.io.json.json_normalize
вместо pd.json_normalize
.