Преобразование сложного xml в фреймворк pandas
Есть целое большое количество из подобных вопросов к этому здесь, на Stackru. Прошу прощения, если это повторится, но я не думаю, что это так, и я пробовал методы, описанные в других ответах, и они не решили проблему.
Я пробовал несколько методов преобразования XML-данных в фреймворк pandas с использованием ряда пакетов (xmltodict
, xmldataset
, и Python ElementTree
). Однако в имеющихся у меня xml-данных больше подмножеств, чем в любом из примеров / ответов, которые я видел, и эти методы не дают мне результатов, которые я ищу.
По соображениям конфиденциальности я не могу предоставить полный доступ к XML-файлу, но расскажу как можно подробнее. Я читаю XML-данные с URL-адреса на OrderedDict, используяxmltodict
вот так
import requests
import xmltodict
url = "myurl"
response = requests.get(url)
data = xmltodict.parse(response.content)
data
Мои данные XML теперь выглядят как OrderedDict с несколькими подмножествами OrderedDicts.
OrderedDict([('weatherdata',
OrderedDict([('@xml',
'http://url.com'),
('@xsi:',
'http://url.com'),
('@created', '2020-07-01T12:42:07Z'),
('meta',
OrderedDict([('model',
[OrderedDict([('@name', ''),
('@termin',
'2020-07-01T06:00:00Z'),
('@runended',
'2020-07-01T09:24:39Z'),
('@nextrun',
'2020-07-01T16:00:00Z'),
('@from',
'2020-07-01T13:00:00Z'),
('@to',
'2020-07-03T12:00:00Z')]),
OrderedDict([('@name',
'ec_n1280_1hr'),
('@termin',
'2020-07-01T00:00:00Z'),
('@runended',
'2020-07-01T09:24:38Z'),
('@nextrun',
'2020-07-01T18:00:00Z'),
('@from',
'2020-07-03T13:00:00Z'),
('@to',
'2020-07-04T18:00:00Z')]),
OrderedDict([('@name',
'ec_n1280_3hr'),
('@termin',
'2020-07-01T00:00:00Z'),
('@runended',
'2020-07-01T09:24:38Z'),
('@nextrun',
'2020-07-01T18:00:00Z'),
('@from',
'2020-07-04T21:00:00Z'),
('@to',
'2020-07-07T00:00:00Z')]),
OrderedDict([('@name',
'ec_n1280_6hr'),
('@termin',
'2020-07-01T00:00:00Z'),
('@runended',
'2020-07-01T09:24:39Z'),
('@nextrun',
'2020-07-01T18:00:00Z'),
('@from',
'2020-07-07T06:00:00Z'),
('@to',
'2020-07-11T00:00:00Z')])])])),
('product',
OrderedDict([('@class', 'pointData'),
('time',
[OrderedDict([('@datatype',
'forecast'),
('@from',
'2020-07-01T13:00:00Z'),
('@to',
'2020-07-01T13:00:00Z'),
('location',
OrderedDict([('@altitude',
'10'),
('@latitude',
'53'),
('@longitude',
'-6'),
('temperature',
OrderedDict([('@id',
'TTT'),
('@unit',
'celsius'),
('@value',
'14.1')])),
('windDirection',
OrderedDict([('@id',
'dd'),
('@deg',
'275.6'),
('@name',
'W')])),
('windSpeed',
OrderedDict([('@id',
'ff'),
('@mps',
'2.1'),
('@beaufort',
'2'),
('@name',
'Svak vind')])),
('globalRadiation',
OrderedDict([('@value',
'67.9'),
('@unit',
'W/m^2')])),
('humidity',
OrderedDict([('@value',
'94.8'),
('@unit',
'percent')])),
('pressure',
OrderedDict([('@id',
'pr'),
('@unit',
'hPa'),
('@value',
'1004.7')])),
('cloudiness',
OrderedDict([('@id',
'NN'),
('@percent',
'100.0')])),
('lowClouds',
OrderedDict([('@id',
'LOW'),
('@percent',
'100.0')])),
('mediumClouds',
OrderedDict([('@id',
'MEDIUM'),
('@percent',
'82.7')])),
('highClouds',
OrderedDict([('@id',
'HIGH'),
('@percent',
'0.0')])),
('dewpointTemperature',
OrderedDict([('@id',
'TD'),
('@unit',
'celsius'),
('@value',
'13.4')]))]))]),
OrderedDict([('@datatype',
'forecast'),
('@from',
'2020-07-01T12:00:00Z'),
('@to',
'2020-07-01T13:00:00Z'),
('location',
OrderedDict([('@altitude',
'10'),
('@latitude',
'53'),
('@longitude',
'-6'),
('precipitation',
OrderedDict([('@unit',
'mm'),
('@value',
'0.4'),
('@minvalue',
'0.2'),
('@maxvalue',
'1.0'),
('@probability',
'68.2')])),
('symbol',
OrderedDict([('@id',
'LightRain'),
('@number',
'9')]))]))]),
OrderedDict([('@datatype',
'forecast'),
('@from',
'2020-07-01T14:00:00Z'),
('@to',
'2020-07-01T14:00:00Z'),
('location',
OrderedDict([('@altitude',
'10'),
('@latitude',
'53'),
('@longitude',
'-6'),
('temperature',
OrderedDict([('@id',
'TTT'),
('@unit',
'celsius'),
('@value',
'14.1')])),
('windDirection',
OrderedDict([('@id',
'dd'),
('@deg',
'350.4'),
('@name',
'N')])),
('windSpeed',
OrderedDict([('@id',
'ff'),
('@mps',
'2.8'),
('@beaufort',
'2'),
('@name',
'Svak vind')])),
('globalRadiation',
OrderedDict([('@value',
'38.9'),
('@unit',
'W/m^2')])),
('humidity',
OrderedDict([('@value',
'92.4'),
('@unit',
'percent')])),
('pressure',
OrderedDict([('@id',
'pr'),
('@unit',
'hPa'),
('@value',
'1004.8')])),
('cloudiness',
OrderedDict([('@id',
'NN'),
('@percent',
'100.0')])),
('lowClouds',
OrderedDict([('@id',
'LOW'),
('@percent',
'100.0')])),
('mediumClouds',
OrderedDict([('@id',
'MEDIUM'),
('@percent',
'64.8')])),
('highClouds',
OrderedDict([('@id',
'HIGH'),
('@percent',
'0.0')])),
('dewpointTemperature',
OrderedDict([('@id',
'TD'),
('@unit',
'celsius'),
('@value',
'13.0')]))]))]),
OrderedDict([('@datatype',
'forecast'),
('@from',
'2020-07-01T13:00:00Z'),
('@to',
'2020-07-01T14:00:00Z'),
('location',
OrderedDict([('@altitude',
'10'),
('@latitude',
'53'),
('@longitude',
'-6'),
('precipitation',
OrderedDict([('@unit',
'mm'),
('@value',
'0.3'),
('@minvalue',
'0.2'),
('@maxvalue',
'0.7'),
('@probability',
'59.3')])),
('symbol',
OrderedDict([('@id',
'LightRain'),
('@number',
'9')]))]))]),
Это небольшой участок данных, там еще сотни строк. Данные имеют несколько слоев, которые я могу распечатать:
[elem.tag for elem in root.iter()]
['weatherdata',
'meta',
'model',
'model',
'model',
'model',
'product',
'time',
'location',
'temperature',
'windDirection',
'windSpeed',
'globalRadiation',
'humidity',
'pressure',
'cloudiness',
'lowClouds',
'mediumClouds',
'highClouds',
'dewpointTemperature',
'time',
'location',
'precipitation',
'symbol']
Метод, который приблизил меня к тому, что я хочу, заключался в подмножестве фрейма данных следующим образом:
df = pd.DataFrame(data["weatherdata"]['product']["time"])
df.head()
который дает фрейм данных, отсортированный по метке времени, но переменная 'location' содержит несколько словарей с переменными среды.
Затем я могу извлечь их:
df = df['location'].apply(pd.Series)
df
Но у этого все еще есть словари в переменных среды, поэтому я думаю, что должен быть лучший способ сделать это. Переменные широты, долготы и высоты являются константами и не обязательно должны быть в данных, мне просто нужны переменные среды.
Я хочу создать фрейм данных для переменных окружения, в каждой строке которого указано время, когда было произведено наблюдение, которое, надеюсь, будет выглядеть примерно так:
Еще одна сложность заключается в том, что осадки представлены иначе, чем другие переменные окружающей среды, с отдельным временным шагом. Я бы хотел, чтобы это тоже было включено в DataFrame.
Возможно, я делаю это совершенно неправильно, и был бы очень признателен за любой совет или помощь о том, как решить эту проблему.