Я пытаюсь заменить значение в ячейке фрейма данных 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 или нули?
Это хорошая идея, есть какие-нибудь предложения, как это сделать?
После анализа 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, ты все еще можешь использовать ту же логику. Если у вас есть словарь, в котором есть один ключ и т. д., замените его на NaN. (Обратите внимание, что это не то, что вы показываете в своих выводах)
Привет, спасибо @SIGHUP за предоставленные решения, я мог бы добавить кое-что к вашему фрагменту кода и закончил подходом, который, наконец, заменил dicts в ключах JSON нулями.
Проще изменить значения в словаре перед созданием 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
]
}
}
Почему бы не изменить значения в словаре перед созданием DataFrame?