Home > other >  Replace NaN in dictionary
Replace NaN in dictionary

Time:08-28

I have this code that pulls financial instruments info (ETF's) out of an API:

import xlwings as xw
import requests

# Open Excel file and reference ETF names and countries worksheet:
excel_file = xw.Book("""FinMkt.xlsm""")
wsCategparssel = excel_file.sheets["""ETFs Selec"""]

# Payload parameters intros objects:
parETFintro = "name="
parCountryintro = "&country="

# Payload parameters objects pulled from ETF names and countries worksheet:
parETFs = wsCategparssel.range("D2#").options(ndim=1).value
parCountries = wsCategparssel.range("B2#").options(ndim=1).value

# API URL:
url = "https://investing4.p.rapidapi.com/etfs/get-etf-information"

# Loop pull payload for each ETF/country pairing and get each respective response:
for parETF, parCountry in zip(parETFs, parCountries):
    payload =  parETFintro   parETF   parCountryintro   parCountry
    headers = {
        "content-type": "application/x-www-form-urlencoded", 
        "X-RapidAPI-Key": "MY API KEY", 
        "X-RapidAPI-Host": "investing4.p.rapidapi.com"
        }

    response = requests. Request("POST", url, data=payload, headers=headers)

Both parETFs and ParCountries are parameters pulled out of an Excel worksheet dynamic range, which for this example contains 2 items that return the following when print(response. Text):

{"data":{"1-Year Change":"- 4.4%","52 wk Range":"4.7 - 493","Asset Class":NaN,"Average Vol. (3m)":154991.0,"Beta":null,"Dividend Yield":"0.38%","Dividends (TTM)":1.8,"ETF Name":"iShares Self-Driving EV and Tech","Market Cap":null,"Open":4.75,"Prev. Close":4.75,"ROI (TTM)":"-","Shares Outstanding":null,"Todays Range":"4.75 - 4.75","Total Assets":null,"Volume":16129.0},"message":"Success!","status":200}
{"data":{"1-Year Change":"- 11.25%","52 wk Range":"196.61 - 233.92","Asset Class":NaN,"Average Vol. (3m)":779.0,"Beta":null,"Dividend Yield":null,"Dividends (TTM)":null,"ETF Name":"Amundi Euro Corporates UCITS","Market Cap":null,"Open":204.14,"Prev. Close":203.92,"ROI (TTM)":"-","Shares Outstanding":null,"Todays Range":"204.14 - 204.91","Total Assets":null,"Volume":null},"message":"Success!","status":200}

In both instruments Asset Class returns NaN and because of that I keep getting the we found extra characters at the end of the json input error when I try to use its transformed/exported json file into Power Query, so I need to replace those Nan say by - as a workaround.

So I've added a few lines of code towards the end, however the last line {key: "-" if value == np.isnan else value for key, value in data_only.items()} just won't solve my problem as Asset Class still returns NaN when I print(data_only_clean).

import xlwings as xw
import requests
import numpy as np
import json

# Open Excel file and reference ETF names and countries worksheet:
excel_file = xw.Book("""FinMkt.xlsm""")
wsCategparssel = excel_file.sheets["""ETFs Selec"""]

# Payload parameters intros objects:
parETFintro = "name="
parCountryintro = "&country="

# Payload parameters objects pulled from ETF names and countries worksheet:
parETFs = wsCategparssel.range("D2#").options(ndim=1).value
parCountries = wsCategparssel.range("B2#").options(ndim=1).value

# API URL:
url = "https://investing4.p.rapidapi.com/etfs/get-etf-information"

# Loop pull payload for each ETF/country pairing and get each respective response:
for parETF, parCountry in zip(parETFs, parCountries):
    payload =  parETFintro   parETF   parCountryintro   parCountry
    headers = {
        "content-type": "application/x-www-form-urlencoded", 
        "X-RapidAPI-Key": "MY API KEY", 
        "X-RapidAPI-Host": "investing4.p.rapidapi.com"
        }

    response = requests. Request("POST", url, data=payload, headers=headers)
    # Transform the response to JSON format:
    data_list = response.json()
    # Add conditional to skip to next item in case some returns code 400:
    if data_list["status"] != 200:
        continue
    # Extract "data" piece out of the response:
    data Only = data_list["data"]
    # Replace NaN by "-"":
    data_only_clean = {key: "-" if value == np.isnan else value for key, value in data_only.items()}

How can I replace any returned value NaN that might show up under any dictionary key in future API responses by something else that won't give me headaches, such as null or -?

Thanks in advance!

Leonardo

CodePudding user response:

it seems that the way np.isnan is used is wrong:

The way it's supposed to be used is rather np.isnan(value) instead of value==np.isnan

so your last line should be the following :

data_only_clean = {key: "-" if np.isnan(value) else value for key, value in data_only.items()}

if this doesn't work, you can also try to use math.isnan(...) (I hat that problem once):

data_only_clean = {key: "-" if mathisnan(value) else value for key, value in data_only.items()}
  • Related