【问题标题】:Return none if item not available in python [duplicate]如果项目在 python 中不可用,则返回 none [重复]
【发布时间】:2020-04-19 09:28:08
【问题描述】:

我指的是这篇文章中提到的解决方案。

I am trying to convert deeply nested JSON into pandas dataframe

import pandas as pd

records = []

for item in d["Data"]:
    records.append(
        {
            "Type": item["CoinInfo"]["Type"],
            "Name": item["CoinInfo"]["Name"],
            "SUPPLY": item["RAW"]["USD"]["SUPPLY"],
        }
    )


df = pd.DataFrame.from_records(records)

df.head()

这有助于我解析字典中的数据,但是当项目不存在时会出错。如果项目不存在,有没有办法修改此代码以返回 null?请帮忙

【问题讨论】:

  • 哪一项不存在?很想知道哪个是空值,因为我无法识别一个

标签: python json pandas dictionary


【解决方案1】:

你正在寻找https://docs.python.org/3/library/stdtypes.html#dict.get:

d = {}
x = d.get("non_existing_key", default=None)
assert x is None

如果所有嵌套级别都可能缺少项目,请使用此帮助器:

def nested_get(d, *keys, default=None):
    value = d
    try:
        for key in keys:
            value = value[key]
    except KeyError:
        return default
    return value


d = {"key": {}}
x = nested_get(d, "key", "missing_nested_key", default=None)
assert x is None

【讨论】:

    【解决方案2】:

    我看到你提到json_normalize 不适合你。也许,我认为以下代码应该可以解决问题:

    data = pd.json_normalize(d["Data"])
    cols = ["CoinInfo.Type", "CoinInfo.Name", "RAW.USD.SUPPLY"]
    names = {"CoinInfo.Type": "Type", "CoinInfo.Name": "Name", "RAW.USD.SUPPLY": "SUPPLY"}
    
    df = data[cols].rename(names, axis=1)
    

    据我了解,当您使用更大的数据集时,这也具有性能优势。

    【讨论】:

      【解决方案3】:

      使用 try ... except 处理异常将解决问题。

      以下程序使用默认值“无”初始化每条记录。

      只有在没有异常的情况下,才会在 for 循环内更新值(即,只有在找到键的情况下)

      以下是实现异常处理的工作示例:

      # File name: CryptoCompare.py
      
      import pandas as pd
      import requests as requests
      
      def get_cryptocompare_data():
          url = "https://min-api.cryptocompare.com/data/top/mktcapfull?limit=15&tsym=USD"
          data = requests.get(url)
          d = data.json()
          records = []
          for item in d["Data"]:
      
              # Initialize a record with null values
              record = {"Type": None, "Name": None, "Supply": None}
      
              try:
      
                  # Update values for the available keys
                  record["Type"] = item["CoinInfo"]["Type"]
                  record["Name"] = item["CoinInfo"]["Name"]
                  record["Supply"] = item["RAW"]["USD"]["SUPPLY"]
      
                  # Try a key that does not exist
                  # record["Supply"] = item["abc"]["ijk"]["xyz"]
      
              except KeyError:
                  # Handle the exception
                  print("Key not found. Therefore, using the default 'None' value")
      
              # Append record to data set
              records.append(record)
      
          df = pd.DataFrame.from_records(records)
          # Show all records
          print(df)
      
      get_cryptocompare_data()
      
      # End of program
      

      输出(找到所有键):

      > python CryptoCompare.py
      
         Type  Name        Supply
      0     1   BTC  1.833352e+07
      1     1   ETH  1.105811e+08
      2     1   XRP  9.999185e+10
      3     1  GAPS  2.000000e+09
      4     1   CRO  1.000000e+11
      5     1  USDT  4.642367e+09
      6     1   BCH  1.838416e+07
      7     1   PLF  1.000000e+10
      8     1  CTAG  4.000000e+09
      9     1  LINK  1.000000e+09
      

      输出(未找到密钥时):

      > python CryptoCompare.py
      
      Key not found. Therefore, using the default 'None' value
      ...
      
      
      
          Type  Name Supply
      0     1   BTC   None
      1     1   ETH   None
      2     1   XRP   None
      3     1  GAPS   None
      4     1   CRO   None
      5     1  USDT   None
      6     1   BCH   None
      7     1   PLF   None
      8     1  CTAG   None
      9     1  LINK   None
      

      【讨论】:

      • 试过这个.. 但由于“列表索引必须是整数或切片,而不是 str”而出现错误。有什么想法吗?
      • 嗨 Karthik,“列表索引必须是整数”错误通常是由于缺少双引号或不匹配的引号导致在需要数字的地方传递字符串。能否分享完整的错误信息,以便找到根本原因?
      【解决方案4】:

      尝试使用get,如果第一个参数在您的字典中不存在,则返回第二个参数。

      请记住,您不能在None 上使用get,因此如果您想访问嵌套键,并且您不确定根级别键是否存在,请提供一个空字典({} ) 作为第二个参数,以便安全地获取内部密钥。

      这是一个例子:

      import pandas as pd
      
      records = []
      
      for item in d["Data"]:
          usd = item.get("RAW",{}).get("USD",{})
          supply = usd.get("SUPPLY") if type(usd) == dict else usd
          records.append(
              {
                  "Type": item.get("CoinInfo",{}).get("Type"),
                  "Name": item.get("CoinInfo",{}).get("Name"),
                  "SUPPLY": supply
              }
          )
      
      
      df = pd.DataFrame.from_records(records)
      
      df.head()
      

      【讨论】:

      • 谢谢加比普。大多数项目都可以正常工作,但是对于某些项目会出现错误,例如“AttributeError:'str' object has no attribute 'get'”。有什么建议吗?
      • 您只能将get 用于dict。发生错误是因为您将 get 函数应用于字符串而不是 dict。例如,item.get("RAW",{}).get("USD",{}).get("SUPPLY") 如果USD 键有一个字符串值,代码会抛出,因为你不能在它上面运行get("SUPPLY")(只在dicts 上)
      • 感谢您的回复。如果美元有字符串而不是字典,我该如何处理,有什么建议吗?
      • 你想如何从字符串中取出 SUPPLY 键?
      • 所以供应是一个关键,它对某些记录具有价值......无论何时存在......我想把它放入数据框......
      猜你喜欢
      • 2011-09-02
      • 2016-05-25
      • 2022-12-25
      • 2018-06-25
      • 2023-01-12
      • 2012-03-06
      • 2014-02-15
      • 2021-09-10
      • 2013-12-04
      相关资源
      最近更新 更多