Py学习  »  Python

Python:nested for循环被字典中的空值中断

Wler • 2 年前 • 1096 次点击  

我对循环和API非常陌生。我目前正在试用IEX的沙箱来收集财务数据。我所做的是收集IEX支持的股票符号列表,然后使用该列表调用数据并将其附加到数据帧中。问题是,有些年IEX没有特定安全性的数据。我希望在数据帧中保持这种安全性,如果缺少值,就写N/A。我的循环代码如下:

my_columns = ['date','Ticker','Price','o_cash_flow','total_income',
          'total_assets','total_liab','rev','ebit','ttm_eps',
          'shares_out','profit_margin','total_rev','2year_return',
          '1year_return','6month_return','3month_return','1month_return']

financials_df = pd.DataFrame(columns = my_columns)

for symbol_string in symbol_strings:
    batch_api_call_url = f'{sandbox_url}/stable/stock/market/batch?symbols={symbol_string}&types=price,financials,stats,advanced-stats&range=2q&token={token}'
    data = requests.get(batch_api_call_url).json()
    for symbol in symbol_string.split(','):
        print(data[symbol])
        financials_df = financials_df.append(
        pd.Series
     [
            data[symbol]['financials']['financials'][0]['fiscalDate'],
            symbol,
            data[symbol]['price'],
            data[symbol]['financials']['financials'][0]['cashFlow'],
            data[symbol]['financials']['financials'][0]['netIncome'],
            data[symbol]['financials']['financials'][0]['totalAssets'],
            data[symbol]['financials']['financials'][0]['totalLiabilities'],
            data[symbol]['financials']['financials'][0]['revenue'],
            data[symbol]['financials']['financials'][0]['ebit'],
            data[symbol]['stats']['ttmEPS'],
            data[symbol]['stats']['sharesOutstanding'],
            data[symbol]['advanced-stats']['profitMargin'],
            data[symbol]['advanced-stats']['totalRevenue'],
            data[symbol]['stats']['year2ChangePercent'],
            data[symbol]['stats']['year1ChangePercent'],
            data[symbol]['stats']['month6ChangePercent'],
            data[symbol]['stats']['month3ChangePercent'],
            data[symbol]['stats']['month1ChangePercent']
    ],
        index = my_columns),
            ignore_index = True
        )

然后,我收到一个错误“KeyError:‘financials’”,这是因为某些证券缺少第二次调用financials。我希望循环只在dataframe中用N/A替换数据,并在发生这种情况时继续从api调用数据。任何帮助都将不胜感激,谢谢。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/129765
 
1096 次点击  
文章 [ 2 ]  |  最新文章 2 年前
Barmar
Reply   •   1 楼
Barmar    3 年前

检查一下 financials 定义为 if 陈述

if 'financials' in data[symbol]['financials']:
    row =  [
        data[symbol]['financials']['financials'][0]['fiscalDate'],
        symbol,
        data[symbol]['price'],
        data[symbol]['financials']['financials'][0]['cashFlow'],
        data[symbol]['financials']['financials'][0]['netIncome'],
        data[symbol]['financials']['financials'][0]['totalAssets'],
        data[symbol]['financials']['financials'][0]['totalLiabilities'],
        data[symbol]['financials']['financials'][0]['revenue'],
        data[symbol]['financials']['financials'][0]['ebit'],
        data[symbol]['stats']['ttmEPS'],
        data[symbol]['stats']['sharesOutstanding'],
        data[symbol]['advanced-stats']['profitMargin'],
        data[symbol]['advanced-stats']['totalRevenue'],
        data[symbol]['stats']['year2ChangePercent'],
        data[symbol]['stats']['year1ChangePercent'],
        data[symbol]['stats']['month6ChangePercent'],
        data[symbol]['stats']['month3ChangePercent'],
        data[symbol]['stats']['month1ChangePercent']
    ]
else:
    row = [
        'N/A',
        symbol,
        data[symbol]['price'],
        'N/A',
        'N/A',
        'N/A',
        'N/A',
        'N/A',
        'N/A',
        data[symbol]['stats']['ttmEPS'],
        data[symbol]['stats']['sharesOutstanding'],
        data[symbol]['advanced-stats']['profitMargin'],
        data[symbol]['advanced-stats']['totalRevenue'],
        data[symbol]['stats']['year2ChangePercent'],
        data[symbol]['stats']['year1ChangePercent'],
        data[symbol]['stats']['month6ChangePercent'],
        data[symbol]['stats']['month3ChangePercent'],
        data[symbol]['stats']['month1ChangePercent']
    ]
financials_df = financials_df.append(pd.Series(row, index=my_columns), ignore_index=True)
jsbueno
Reply   •   2 楼
jsbueno    3 年前

你有这个用途 .get 方法而不是 [...] 检索值的语法。这允许您为缺失案例添加默认值。 但是,由于您是用硬编码的dict查询构建的,因此必须级联 get s用于嵌套字段检索,如果可靠的话,这可能会变得很长。 而且 收到 不检查序列中的元素:尝试从空序列检索索引0处的元素也会出错。

所以 data[symbol]['financials']['financials'][0]['netIncome'] 必须成为

(((d3 if (d3:=d2[0].get("netIncome")) else "N/A")if d2 else "N/A" )if (d2:=d1.get('financials') else "N/A") if (d1:=data[symbol].get('financials')) else "N/A"

可以清楚地看到,即使是像您这样的中等结构,这也不可行。最好的方法是构建一个helper函数,从数据的“路径”中检索嵌套数据,默认为一个值,并每次调用该函数:

def retr(obj, path, default="N/A"):
   try:
      for index in path:
          obj = obj[index]
   except (IndexError, KeyError):
      return default
   return obj

他们会打电话给 retr 要组成每个数据项,请执行以下操作:

data[symbol]['financials']['financials'][0]['cashFlow'],

变成:

retr(data, ["symbol", "financials", "financials", 0 ,"cashFlow"]),