Замена значения, поступающего из JSON, в ячейке кадра данных pandas

Я пытаюсь заменить значение в ячейке фрейма данных pandas, которую я создаю из файла JSON, полученного из Airtable API файл JSON выглядит следующим образом:

[
    {
        "id": "rec0Y7ydscZnU5NjZ",
        "createdTime": "2023-03-17T16:32:57.000Z",
        "fields": {
            "field_id": [
                "recq6vsFWI2H8j84i"
            ],
            "field_name": "S-166",
            "currency": [
                "Dolares"
            ],
            "state": [
                5
            ],
            "roi": {
                "specialValue": "Infinity"
            },
            "investment_return": {
                "specialValue": "NaN"
            },
            "value_amount": 16559.51178956216,
            "income": [
                31978.5
            ]
        }       
    }
]

Очевидно, что это образец, и я заменяю реальные ключи и некоторые значения, поскольку они взяты из частного приложения, но то, что я пытаюсь сделать, как только получу ответ API, а затем преобразую JSON в фрейм данных, используя приведенный ниже код: заключается в замене значений {"specialValue": "Infinity"} из ключа roi и {"specialValue": "NaN"} из ключа Investment_return нулями:

#read_json.py
def read_json():
    # Open the JSON file
    with open('json_test.json', 'r') as file:
    # Parse the JSON data
        data = json.load(file)

        # Extract all fields from the "fields" dictionary and create a DataFrame
        df1 = pd.DataFrame([record['id'] for record in data],columns=['id'])
        df2 = pd.DataFrame([record['fields'] for record in data])
        
        df = pd.concat([df1,df2], axis=1)
        
    return df

Затем, как только данные JSON будут преобразованы в фрейм данных, я пытаюсь заменить значения, используя этот код:

df.replace('{"specialValue": "Infinity"}', np.nan, inplace=True)

Почему-то не работает:

Здесь я использую функцию read_json(), описанную выше, для генерации кадра данных из файла JSON, полученного из ответа API, и проверяю полученный фрейм данных:

df = read_json()
print(df)
                  id             field_id field_name   currency state  \
0  rec0Y7ydscZnU5NjZ  [recq6vsFWI2H8j84i]      S-166  [Dolares]   [5]   

                            roi        investment_return  value_amount  \
0  {'specialValue': 'Infinity'}  {'specialValue': 'NaN'}   16559.51179   

      income  
0  [31978.5] 

Затем однажды я хочу, например, replace() строку {"specialValue": "Infinity"} на NaN с numpy:

# replace string value with NaN
df.replace('{"specialValue": "Infinity"}', np.nan, inplace=True)
print(df)

я ожидал бы получить для столбца roi значение nan, но я все равно получаю ту же строку, которую получаю от API:

0  rec0Y7ydscZnU5NjZ  [recq6vsFWI2H8j84i]      S-166  [Dolares]   [5]   

                            roi        investment_return  value_amount  \
0  {'specialValue': 'Infinity'}  {'specialValue': 'NaN'}   16559.51179   

      income  
0  [31978.5]  

Может ли кто-нибудь дать мне возможный подход к преобразованию их в NaN или нули?

Почему бы не изменить значения в словаре перед созданием DataFrame?

SIGHUP 27.05.2024 15:58

Это хорошая идея, есть какие-нибудь предложения, как это сделать?

superunknown 27.05.2024 16:00
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

После анализа JSON у вас больше нет строк, а есть объекты.

В частности, вы можете проверить это:

type(df.at[0, 'investment_return'])
# dict

Вы можете воспользоваться изменчивостью словарей и методом карты (applymap до версии pandas 2.1):

def replace_in_dict(x):
    if isinstance(x, dict) and 'specialValue' in x and x['specialValue'] == 'Infinity':
        x['specialValue'] = 'NaN'

df.map(replace_in_dict)

print(df)

Изменено df:

                  id             field_id field_name   currency state                      roi        investment_return  value_amount     income
0  rec0Y7ydscZnU5NjZ  [recq6vsFWI2H8j84i]      S-166  [Dolares]   [5]  {'specialValue': 'NaN'}  {'specialValue': 'NaN'}   16559.51179  [31978.5]

Спасибо за ваш вклад @mozway, я действительно хочу заменить не значение «Бесконечность» в паре ключ: значение на «NaN», а заменить всю строку {"specialValue": "Infinity"}, а также другую {"specialValue": "NaN"}, которая соответствует ключу: значение в JSON с помощью nan в сгенерированном кадре данных.

superunknown 27.05.2024 15:56

@superunknown, ты все еще можешь использовать ту же логику. Если у вас есть словарь, в котором есть один ключ и т. д., замените его на NaN. (Обратите внимание, что это не то, что вы показываете в своих выводах)

mozway 27.05.2024 16:32

Привет, спасибо @SIGHUP за предоставленные решения, я мог бы добавить кое-что к вашему фрагменту кода и закончил подходом, который, наконец, заменил dicts в ключах JSON нулями.

superunknown 27.05.2024 22:51
Ответ принят как подходящий

Проще изменить значения в словаре перед созданием DataFrame.

Например:

import json

data = '''
[
    {
        "id": "rec0Y7ydscZnU5NjZ",
        "createdTime": "2023-03-17T16:32:57.000Z",
        "fields": {
            "field_id": [
                "recq6vsFWI2H8j84i"
            ],
            "field_name": "S-166",
            "currency": [
                "Dolares"
            ],
            "state": [
                5
            ],
            "roi": {
                "specialValue": "Infinity"
            },
            "investment_return": {
                "specialValue": "NaN"
            },
            "value_amount": 16559.51178956216,
            "income": [
                31978.5
            ]
        }       
    }
]
'''

for datum in json.loads(data):
    fields = datum.get("fields", {})
    for k in "roi", "investment_return":
        dk = fields.get(k, {})
        if dk.get("specialValue") in {"Infinity", "NaN"}:
            dk["specialValue"] = 0
    print(json.dumps(datum, indent=2))

Выход:

{
  "id": "rec0Y7ydscZnU5NjZ",
  "createdTime": "2023-03-17T16:32:57.000Z",
  "fields": {
    "field_id": [
      "recq6vsFWI2H8j84i"
    ],
    "field_name": "S-166",
    "currency": [
      "Dolares"
    ],
    "state": [
      5
    ],
    "roi": {
      "specialValue": 0
    },
    "investment_return": {
      "specialValue": 0
    },
    "value_amount": 16559.51178956216,
    "income": [
      31978.5
    ]
  }
}

Другие вопросы по теме