Как перевести словарь значений NumPy int64 в JSON?
Имею некоторую массу вычислений, основанных на типах данных NumPy и Pandas.
y_true = np.where(true_birads >= birads_thresh, 1, 0)
y_pred = np.where(pred_birads >= birads_thresh, 1, 0)
birads_metrics["Accuracy"] = str(metrics.accuracy_score(true_birads, pred_birads))
birads_metrics["F1-Macro"] = str(metrics.f1_score(true_birads, pred_birads, average="macro"))
f_class = metrics.fbeta_score(true_birads, pred_birads, beta=1.5, average=None)
#birads_metrics["F-weighted"] = np.sum(np.multiply(f_class, weights)) / np.sum(weights)
tn, fp, fn, tp = metrics.confusion_matrix(y_true, y_pred).ravel()
birads_metrics['Confusion Matrix'] = {'TN': str(tn), 'FP': str(fp), 'FN': str(fn), 'TP': str(tp)}
birads_metrics["Specificity"] = tn / (tn + fp)
birads_metrics["Recall"] = metrics.recall_score(y_true, y_pred)
birads_metrics["PPV"] = str(tp / (tp + fp))
birads_metrics["NPV"] = str(tn / (tn + fn))
birads_metrics["PPR"] = str(birads_metrics["Recall"] / (1 - birads_metrics["Specificity"]))
birads_metrics["NPR"] = str((1 - birads_metrics["Recall"]) / birads_metrics["Specificity"])
birads_metrics["Recall"] = str(birads_metrics["Recall"])
birads_metrics["Specificity"] = str(birads_metrics["Specificity"])
Задача - сконвертировать словарь birads_metrics в JSON для последующей отправки в jsonb-столбец postgresql через requests и API на Django Rest Farmework.
Проблема: значения numpy in64 не конвертируются в JSON функцией json.dumps(), попытка вручную сформировать строку, идентичную json, приводит к ругани от DRF на некорректность формата json. Как видно из кода, преобразование всех значений в строку даёт нужный результат и всё работает отлично. Так же пробовал кастомный класс json.JSONEncoder, но нужного результата это не принесло. Текущий вариант со строками выглядит просто ужасно. Посоветуйте, как можно поступить в данной ситуации для автоматизированного преобразования в строки.
class NpEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
return int(obj)
elif isinstance(obj, np.floating):
return float(obj)
elif isinstance(obj, np.ndarray):
return str(obj.tolist())
else:
return super(NpEncoder, self).default(obj)
Ответы (2 шт):
Воспользуйтесь функцией DataFrame.to_json():
import json
df = pd.DataFrame(
[["a", "b"], ["c", "d"]],
index=["row 1", "row 2"],
columns=["col 1", "col 2"],
)
result = df.to_json(orient="split")
parsed = json.loads(result)
результат:
>>>json.dumps(parsed, indent=4)
{
"columns": [
"col 1",
"col 2"
],
"index": [
"row 1",
"row 2"
],
"data": [
[
"a",
"b"
],
[
"c",
"d"
]
]
}
Решение похоже найдено. Был изменен класс JSONEncoder.
class NpEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.float64):
return float(obj)
elif isinstance(obj, np.int64):
return int(obj)
return str(obj)
result_json = json.dumps(birads_metrics, cls=NpEncoder)
Это решение помогло.