На самом деле мы можем немного упростить этот код, чтобы получить желаемый результат (и упростить его настройку в будущем!)
Готовый код приведен здесь, с более подробными пояснениями ниже:
import numpy as np
import json
import pandas as pd
import requests
content = requests.get(r'https://eodhistoricaldata.com/api/fundamentals/AAPL.US?api_token=OeAFFmMliFG5orCUuwAKQ8l4WWFQ67YX')
income_data = content.json()['Financials']['Income_Statement']['quarterly']
income = pd.DataFrame.from_dict(income_data).transpose().set_index("date")
income = income[['ebit']]
balance_data = content.json()['Financials']['Balance_Sheet']['quarterly']
balance = pd.DataFrame.from_dict(balance_data).transpose().set_index("date")
balance = balance[['totalAssets', 'cash', 'totalCurrentAssets', 'totalCurrentLiabilities']]
financials = income.merge(balance, left_index = True, right_index = True).fillna(0)
Финансовый DataFrame будет выглядеть следующим образом (показаны только данные за 2005-2009 гг.):
| date | ebit | totalAssets | cash | totalCurrentAssets | totalCurrentLiabilities |
|:-----------|----------:|--------------:|-----------:|---------------------:|--------------------------:|
| 2009-12-26 | 4.758e+09 | 5.3926e+10 | 7.609e+09 | 3.3332e+10 | 1.3097e+10 |
| 2009-09-26 | 0 | 4.7501e+10 | 5.263e+09 | 3.1555e+10 | 1.1506e+10 |
| 2009-06-27 | 1.732e+09 | 4.814e+10 | 5.605e+09 | 3.517e+10 | 1.6661e+10 |
| 2009-03-31 | 0 | 4.3237e+10 | 4.466e+09 | 0 | 1.3751e+10 |
| 2008-12-31 | 0 | 4.2787e+10 | 7.236e+09 | 0 | 1.4757e+10 |
| 2008-09-30 | 0 | 3.9572e+10 | 1.1875e+10 | 0 | 1.4092e+10 |
| 2008-06-30 | 0 | 3.1709e+10 | 9.373e+09 | 0 | 9.218e+09 |
| 2008-03-31 | 0 | 3.0471e+10 | 9.07e+09 | 0 | 9.634e+09 |
| 2007-12-31 | 0 | 3.0039e+10 | 9.162e+09 | 0 | 1.0535e+10 |
| 2007-09-30 | 0 | 2.5347e+10 | 9.352e+09 | 0 | 9.299e+09 |
| 2007-06-30 | 0 | 2.1647e+10 | 7.118e+09 | 0 | 6.992e+09 |
| 2007-03-31 | 0 | 1.8711e+10 | 7.095e+09 | 0 | 5.485e+09 |
| 2006-12-31 | 0 | 1.9461e+10 | 7.159e+09 | 0 | 7.337e+09 |
| 2006-09-30 | 0 | 1.7205e+10 | 6.392e+09 | 0 | 6.471e+09 |
| 2006-06-30 | 0 | 1.5114e+10 | 0 | 0 | 5.023e+09 |
| 2006-03-31 | 0 | 1.3911e+10 | 0 | 0 | 4.456e+09 |
| 2005-12-31 | 0 | 1.4181e+10 | 0 | 0 | 5.06e+09 |
| 2005-09-30 | 0 | 1.1551e+10 | 3.491e+09 | 0 | 3.484e+09 |
| 2005-06-30 | 0 | 1.0488e+10 | 0 | 0 | 3.123e+09 |
| 2005-03-31 | 0 | 1.0111e+10 | 0 | 0 | 3.352e+09 |
Результат content.json()['Financials']['Income_Statement']['quarterly']
- это словарь, в котором каждый ключ является дата и каждое значение являются вторым словарем с данными столбца.
{'2005-03-31': {'date': '2005-03-31',
'filing_date': None,
'currency_symbol': 'USD',
'researchDevelopment': '120000000.00',
...},
'2005-06-30': {...},
...}
Поскольку это так, вы можете загрузить этот словарь непосредственно в pandas фрейм данных, используя
pd.DataFrame.from_dict(income_data).transpose().set_index("date")
Транспонирование необходимо, потому что структуры JSON. Pandas ожидает словарь в формате {'column name': data}
. Поскольку ключи являются датами, первоначально вы получите DataFrame, где строки помечены как «totalAssets», «ca sh» и т. Д. c. и столбцы даты. команда transpose()
переворачивает строки и столбцы в нужном вам формате. Последняя команда .set_index("date")
предназначена для использования данных «дата» вместо начальной контрольной даты для согласованности и присвоения имени индексу. Это совершенно необязательно
Теперь этот DataFrame будет иметь каждый столбец из файла JSON, но вас интересуют только некоторые. Код
income = income[['ebit']]
выбирает только соответствующие столбцы из данных.
Поскольку вы извлекаете данные из двух разных источников, вам необходимо создать две разные таблицы , Это дает дополнительное преимущество: вы можете более четко видеть, какие столбцы извлекаются из «Отчета о прибылях и убытках», а какие из «Бухгалтерского баланса».
Финальная строка
financials = income.merge(balance, left_index = True, right_index = True).fillna(0)
объединяет две таблицы вместе, используя их индексы (в данном случае, столбец «дата»). fillna(0)
гарантирует, что любые отсутствующие данные будут заменены нулевым значением, как вы и просили.
Если вам в конечном итоге понадобится добавить еще одну таблицу, например «Cash_Flow», вы будете использовать те же строки кода для создайте таблицу, выберите соответствующие столбцы и добавьте вторую строку слияния:
cashflow_data = content.json()['Financials']['Balance_Sheet']['quarterly']
cashflow = pd.DataFrame.from_dict(cashflow_data).transpose().set_index("date")
cashflow = cashflow[['accountsPayable', 'liabilitiesAndStockholdersEquity']]
...
financials.merge(cashflow, left_index = True, right_index = True).fillna(0)
В качестве бонуса, в вашем источнике довольно много данных JSON! Чтобы увидеть, какие столбцы доступны вам в любой данной таблице, используйте следующую команду:
cashflow.columns.sort_values()
, чтобы получить алфавитный список столбцов, которые вы можете использовать:
['accountsPayable', 'accumulatedAmortization', 'accumulatedDepreciation',
'accumulatedOtherComprehensiveIncome', 'additionalPaidInCapital',
'capitalLeaseObligations', 'capitalSurpluse', 'cash',
'cashAndShortTermInvestments', 'commonStock',
'commonStockSharesOutstanding', 'commonStockTotalEquity',
'currency_symbol', 'deferredLongTermAssetCharges',
'deferredLongTermLiab', 'filing_date', 'goodWill', 'intangibleAssets',
'inventory', 'liabilitiesAndStockholdersEquity', 'longTermDebt',
'longTermDebtTotal', 'longTermInvestments', 'negativeGoodwill',
'netReceivables', 'netTangibleAssets', 'nonCurrentAssetsTotal',
'nonCurrentLiabilitiesOther', 'nonCurrentLiabilitiesTotal',
'nonCurrrentAssetsOther', 'noncontrollingInterestInConsolidatedEntity',
'otherAssets', 'otherCurrentAssets', 'otherCurrentLiab', 'otherLiab',
'otherStockholderEquity', 'preferredStockRedeemable',
'preferredStockTotalEquity', 'propertyPlantAndEquipmentGross',
'propertyPlantEquipment', 'retainedEarnings',
'retainedEarningsTotalEquity', 'shortLongTermDebt', 'shortTermDebt',
'shortTermInvestments',
'temporaryEquityRedeemableNoncontrollingInterests', 'totalAssets',
'totalCurrentAssets', 'totalCurrentLiabilities', 'totalLiab',
'totalPermanentEquity', 'totalStockholderEquity', 'treasuryStock',
'warrants']
Это также очень полезно, когда в данных есть ошибки, например, в "capitalSurpluse" выше.