Я новичок в python, и я пытаюсь добиться следующего.
У меня есть этот словарь:
cust_DB = {'cust_ID': {'NAME': 'name', 'ADDRESS': 'address', 'PHONES': {'HOME_PHONE': 'home#', 'WORK_PHONE': 'work#', 'MOBILE_PHONE': 'mobile#'}, 'EMAILS': {'HOME_EMAIL': 'email@home', 'WORK_EMAIL': 'email@work'}
Я хотел бы преобразовать и поместить этот словарь в фрейм данных pandas df со следующими столбцами df и соответствующими записями:
'ID'|'NAME'|'ADDRESS'|'HOME_PHONE'|'WORK_PHONE'|'MOBILE_PHONE'|'HOME_EMAIL'|'WORK_EMAIL'
Если я использую pandas.DataFrame.from_dict(), вложенные номера телефонов и электронные письма группируются в один столбец каждый. Есть ли быстрый способ заполнить этот фрейм данных?
Спасибо!
Давайте попробуем эту пользовательскую функцию flatten
:
def flatten(d):
ret = dict()
for k, v in d.items():
if isinstance(v, dict):
sub = flatten(v)
for kk, vv in sub.items():
ret[kk] = vv
else: ret[k] = v
return ret
out = pd.DataFrame({k:flatten(v) for k, v in cust_DB.items()})
out = out.T.rename_axis('ID').reset_index()
Выход:
ID ADDRESS HOME_EMAIL HOME_PHONE MOBILE_PHONE NAME WORK_EMAIL WORK_PHONE
-- ------- --------- ------------ ------------ -------------- ------ ------------ ------------
0 cust_ID address email@home home# mobile# name email@work work#
Мой ответ ниже очень длинный.
Тем не менее, я верю в следующую старую поговорку:
Если дать человеку рыбу, он будет сыт один день.
Если научить человека ловить рыбу, он будет сыт всю жизнь.
У вас есть словарь словарей.
Я рекомендую вам визуализировать вложенный словарь в виде дерева:
"Лист" - это просто узел (узлы - круг/точка) в дереве, у которого нет дочерних элементов. «Листья» подобны людям-холостякам или старым девам: у них нет детей.
Похоже, вы хотите одну из следующих двух вещей. Я не уверен, какой ....
Это часто называют «сплющиванием» дерева.
cust_DB = {'cust_ID': {'NAME': 'name', 'ADDRESS': 'address', 'PHONES': {'HOME_PHONE': 'home#', 'WORK_PHONE': 'work#', 'MOBILE_PHONE': 'mobile#'}, 'EMAILS': {'HOME_EMAIL': 'email@home', 'WORK_EMAIL': 'email@work'}}}
def flatten(parent):
"""
[* crickets chirping for lack of code-comments* ]
"""
if not hasattr(parent, '__iter__'):
return parent
leaves = list()
root_type = type(parent)
for child_key in iter(parent):
child = parent[child_key]
if type(child) == type(parent):
subleaves = flatten(child)
leaves.extend(subleaves)
else:
leaves.append(child)
return leaves
leaves = flatten(cust_DB)
result = "\n".join(map(str, iter(leaves)))
print(result)
Я вижу это:
Я рекомендую следующее решение:
flatten
, чтобы получить родителей листовых узлов вместо листьев.Если вы никогда не знали о поиске в глубину или поиске в ширину, я рекомендую посмотреть видео на YouTube по этим темам.
Возникает одна проблема:
итераторы списков python возвращают значения, а не ключ. итераторы словарей Python возвращают ключи, а не значения.
Python — это то, что мне нравится называть языком «два шага вперед, один шаг назад». То есть Python в чем-то лучше старых языков (таких как C), а в чем-то хуже.
Если бы Python был хорошо спроектирован, все встроенные контейнеры (list
, dict
и т. д.) различали бы итераторы ключей и итераторы значений.
lyst = ["Spam", "Toast", "Eggs"]
# The keys (inputs) of lyst are:
# 0, 1, 2
# The values (outputs) of `lyst` are:
# Spam", "Toast", and "Eggs"
dyct = {0: "Spam", 1:"Toast", 2:"Eggs"}
# The keys (inputs) of dyct are:
# 0, 1, 2
# The values (outputs) of `dyct` are:
# Spam", "Toast", and "Eggs"
print("LIST STUFF IS BELOW")
for element in lyst:
print(element)
print(end = "\n")
print("DICT STUFF IS BELOW")
for element in dyct:
print(element)
Вы могли бы подумать, что вывод будет одинаковым как для списков, так и для словарей, но вывод отличается.
LIST STUFF IS BELOW
Spam
Toast
Eggs
DICT STUFF IS BELOW
0
1
2
Вы должны быть очень внимательны и заранее знать, является ли контейнер словарем или списком. В противном случае ваши циклы for будут перебирать индексы/ключи (входы) вместо значений (выходов).
#####################################
# BEGIN CODE FOR LISTS
#####################################
for child in parent:
flatten(child) # FOR LISTS
#####################################
# END OF CODE FOR LISTS
#---------------------------
# BEGIN CODE FOR DICTIONARIES
#####################################
for child_key in parent:
child = parent[child_key] # FOR DICTIONARIES
flatten(child)
#####################################
# END OF CODE FOR DICTIONARIES
#####################################