#python #pandas #dataframe #split
#python #панды #фрейм данных #сплит
Вопрос:
Я прочитал несколько сообщений, но мне не удалось получить то, что я хочу. У меня есть фрейм данных с ~ 4k строками и несколькими столбцами, которые я экспортировал из Infoblox (DNS-сервер). Одним из них являются атрибуты dhcp, и я хотел бы расширить его, чтобы иметь отдельные значения. Это мой df (я прилагаю скриншот из excel): скриншот Excel
Один из столбцов — это словарь из всех вариантов, это пример (очищенный):
[
{"name": "tftp-server-name", "num": 66, "value": "10.70.0.27", "vendor_class": "DHCP"},
{"name": "bootfile-name", "num": 67, "value": "pxelinux.0", "vendor_class": "DHCP"},
{"name": "dhcp-lease-time", "num": 51, "use_option": False, "value": "21600", "vendor_class": "DHCP"},
{"name": "domain-name-servers", "num": 6, "use_option": False, "value": "10.71.73.143,10.71.74.163", "vendor_class": "DHCP"},
{"name": "domain-name", "num": 15, "use_option": False, "value": "example.com", "vendor_class": "DHCP"},
{"name": "routers", "num": 3, "use_option": True, "value": "10.70.1.200", "vendor_class": "DHCP"},
]
Я хотел бы расширить этот столбец до некоторых (до той же строки), например, так.
Использование «name» в качестве столбца df и «value» в качестве значения строки.
Это и было бы целью:
tftp-server-name voip-tftp-server dhcp-lease-time domain-name-server domain-name routers
0 10.71.69.58 10.71.69.58,10.71.69.59 86400 10.71.73.143,10.71.74.163 example.com 10.70.12.254
Чтобы иметь глобальный df со всей информацией, я думаю, мне следует создать новый df, сохранив индекс для слияния с основным, но я не смог этого сделать.
Я пробовал использовать expand, append, explode…
Пожалуйста, не могли бы вы мне помочь?
Большое вам спасибо за ваше решение (для обоих). Я мог бы заставить это работать, это мой последний файл: я мог бы это сделать. Я добавляю полное решение, на всякий случай, если оно кому-то понадобится (возможно, есть более питонический способ, но он работает).:
def formato(df):
opciones = df['options']
df_int = pd.DataFrame()
for i in opciones:
df_int = df_int.append(pd.DataFrame(i).set_index("name")[["value"]].T.reset_index(drop=True))
df_int.index = range(len(df_int.index))
df_global = pd.merge(df, df_int, left_index=True, right_index=True, how="inner")
df_global = df.rename(columns={"comment": "Comentario", "end_addr": "IP Fin", "network": "Red",
"start_addr": "IP Inicio", "disable": "Deshabilitado"})
df_global = df_global[["Red", "Comentario", "IP Inicio", "IP Fin", "dhcp-lease-time",
"domain-name-servers", "domain-name", "routers", "tftp-server-name", "bootfile-name",
"voip-tftp-server", "wdm-server-ip-address", "ftp-file-server", "vendor-encapsulated-options"]]
return df_global
Ответ №1:
Вот одно из решений:
import pandas as pd
data = [{'name': 'tftp-server-name', 'num': 66, 'value': '10.70.0.27', 'vendor_class': 'DHCP'}, {'name': 'bootfile-name', 'num': 67, 'value': 'pxelinux.0', 'vendor_class': 'DHCP'}, {'name': 'dhcp-lease-time', 'num': 51, 'use_option': False, 'value': '21600', 'vendor_class': 'DHCP'}, {'name': 'domain-name-servers', 'num': 6, 'use_option': False, 'value': '10.71.73.143,10.71.74.163', 'vendor_class': 'DHCP'}, {'name': 'domain-name', 'num': 15, 'use_option': False, 'value': 'example.com', 'vendor_class': 'DHCP'}, {'name': 'routers', 'num': 3, 'use_option': True, 'value': '10.70.1.200', 'vendor_class': 'DHCP'}]
df = pd.DataFrame(data).set_index("name")[["value"]].T.reset_index(drop=True)
вывод:
name tftp-server-name bootfile-name dhcp-lease-time domain-name-servers domain-name routers
0 10.70.0.27 pxelinux.0 21600 10.71.73.143,10.71.74.163 example.com 10.70.1.200
Комментарии:
1. Привет @anon01, спасибо за ваш ответ, но я не смог достичь цели. Я хочу преобразовать всю серию pandas, но когда я прочитал ее, я получаю ее как «str», и я не могу создать новый фрейм данных.
2. Я пытаюсь привести небольшой пример:
opciones = df.loc[0:5, 'options'] for i in opciones: print(type(i)) --> <class 'str'>
3. Как правильно читать df [‘options’], чтобы получить эти списки, чтобы я мог преобразовать их, как вы сказали?
Ответ №2:
Вы можете использовать json_normalize
следующее:
from pandas.io.json import json_normalize
import ast
import pandas as pd
def extract_dict(ld):
res ={}
for d in ast.literal_eval(ld):
res[d['name']] = d['value']
return res
# load dataframe (I made a dummy, replace it with read from file)
df = pd.DataFrame.from_dict({'temp':['temp'],'option':['''[{'name': 'tftp-server-name', 'num': 66, 'value': '10.70.0.27', 'vendor_class': 'DHCP'}, {'name': 'bootfile-name', 'num': 67, 'value': 'pxelinux.0', 'vendor_class': 'DHCP'}, {'name': 'dhcp-lease-time', 'num': 51, 'use_option': False, 'value': '21600', 'vendor_class': 'DHCP'}, {'name': 'domain-name-servers', 'num': 6, 'use_option': False, 'value': '10.71.73.143,10.71.74.163', 'vendor_class': 'DHCP'}, {'name': 'domain-name', 'num': 15, 'use_option': False, 'value': 'example.com', 'vendor_class': 'DHCP'}, {'name': 'routers', 'num': 3, 'use_option': True, 'value': '10.70.1.200', 'vendor_class': 'DHCP'}]''']})
B = json_normalize(df['option'].apply(extract_dict).tolist())
print(B)
Результат выглядит следующим образом:
tftp-server-name bootfile-name dhcp-lease-time domain-name-servers domain-name routers
0 10.70.0.27 pxelinux.0 21600 10.71.73.143,10.71.74.163 example.com 10.70.1.200