У меня сложная задача: загрузить json файл из формата и перекодировать в другом формате для загрузки в MongoDB. Мой json файл от Alpha Vantage (https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=demo) и имеет следующий формат.
"Time Series (1min)": {
"2018-07-13 16:00:00": {
"1. open": "105.4550",
"2. high": "105.5600",
"3. low": "105.3900",
"4. close": "105.4300",
"5. volume": "2484606"
},
"2018-07-13 15:59:00": {
"1. open": "105.5300",
"2. high": "105.5300",
"3. low": "105.4500",
"4. close": "105.4600",
"5. volume": "216617"
}
Мне нужно повторно закодировать файл в соответствии со следующей схемой, используя День, час и минуту как ключи.
{
'2018-07-13': {
'16': {
'00': {'open': 105.4550,
'high': 105.5600,
'low': 105.3900,
'close': 105.4300,
'volume': 2484606,}
}
}
'2018-07-13': {
'15': {
'59': {'open': 105.53000,
'high': 105.5300,
'low': 105.4500,
'close': 105.4600,
'volume': 6484606,}
}
}
}
Я провел много исследований, но я не понял, как построить словарь с несколькими ключами, используя цикл, в то же время я прочитал json файл, который я бы хотел включить в Dict.
Я согласен, что это может быть немного запутанным, если вы не привыкли работать с вложенными структурами данных, но это не так сложно, если вы будете осторожны. Хитрость заключается в создании внутренних словарей, если они еще не существуют. Мы можем сделать это с dict.setdefault
метода dict.setdefault
.
Нам также необходимо преобразовать внутренние данные из строк в числа. Но мы хотим, чтобы числа были целыми числами, если они не содержат десятичной точки, в противном случае мы хотим поплавки. Обычный способ сделать это показан в моей функции str_to_num
. Сначала мы пытаемся преобразовать в целое число, и если это не удается, мы конвертируем в float. И если это не удается из-за плохих данных, программа повысит исключение ValueError и прекратит работу. Вы можете обращаться с этим по-другому, например, игнорировать плохие данные.
Я предполагаю, что вы знаете, как извлечь нужные данные с внешнего уровня, используя ключ "Time Series (1min)"
. В приведенном ниже коде используется стандартный модуль json
для преобразования данных в новый формат обратно в JSON, чтобы мы могли его распечатать.
import json
alpha_data = {
"2018-07-13 16:00:00": {
"1. open": "105.4550",
"2. high": "105.5600",
"3. low": "105.3900",
"4. close": "105.4300",
"5. volume": "2484606"
},
"2018-07-13 15:59:00": {
"1. open": "105.5300",
"2. high": "105.5300",
"3. low": "105.4500",
"4. close": "105.4600",
"5. volume": "216617"
}
}
def str_to_num(s):
try:
n = int(s)
except ValueError:
n = float(s)
return n
# Where we'll store the output
out_data = {}
for timestamp, data in alpha_data.items():
datestr, timestr = timestamp.split()
hr, mn, _ = timestr.split(':')
# Fetch inner dicts, creating them if they don't exist yet
d = out_data.setdefault(datestr, {})
d = d.setdefault(hr, {})
d[mn] = {k.split()[1]: str_to_num(v) for k, v in data.items()}
print(json.dumps(out_data, indent=4))
выход
{
"2018-07-13": {
"16": {
"00": {
"open": 105.455,
"high": 105.56,
"low": 105.39,
"close": 105.43,
"volume": 2484606
}
},
"15": {
"59": {
"open": 105.53,
"high": 105.53,
"low": 105.45,
"close": 105.46,
"volume": 216617
}
}
}
}
Вы заметите, что мой вывод не совсем то же самое, что и ваш желаемый результат. Это потому, что ключи в словарях Python уникальны: у вас не может быть двух элементов в одном и том же dict
с ключом "2018-07-13"
. Таким образом, мой код создает dict
в out_data
с ключом "2018-07-13"
и внутри этого dict он при необходимости создает dict для каждого часа.
dict
для каждого дня, который он видит во входных данных.