Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

247
Views
¿Cómo obtener una representación exacta de los flotadores durante `DataFrame.to_json`?

Observé el siguiente comportamiento con DataFrame.to_json :

 >>> df = pd.DataFrame([[eval(f'1.12345e-{i}') for i in range(8, 20)]]) >>> df 0 1 2 3 4 5 6 7 8 9 10 11 0 1.123450e-08 1.123450e-09 1.123450e-10 1.123450e-11 1.123450e-12 1.123450e-13 1.123450e-14 1.123450e-15 1.123450e-16 1.123450e-17 1.123450e-18 1.123450e-19 >>> print(df.to_json(indent=2, orient='index')) { "0":{ "0":0.0000000112, "1":0.0000000011, "2":0.0000000001, "3":0.0, "4":0.0, "5":0.0, "6":0.0, "7":0.0, "8":1.12345e-16, "9":1.12345e-17, "10":1.12345e-18, "11":1.12345e-19 } }

Entonces, todos los números hasta 1e-16 parecen estar redondeados a 10 lugares decimales (de acuerdo con el valor predeterminado para double_precision ), pero todos los valores más pequeños se representan exactamente. ¿Por qué es este el caso y cómo puedo desactivar el redondeo decimal también para los valores más grandes (es decir, usar notación científica en su lugar)?


 >>> pd.__version__ '1.3.1'

Como referencia, el módulo json de la biblioteca estándar no hace esto:

 >>> import json >>> print(json.dumps([eval(f'1.12345e-{i}') for i in range(8, 20)], indent=2)) [ 1.12345e-08, 1.12345e-09, 1.12345e-10, 1.12345e-11, 1.12345e-12, 1.12345e-13, 1.12345e-14, 1.12345e-15, 1.12345e-16, 1.12345e-17, 1.12345e-18, 1.12345e-19 ]
over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Se refiere a la base de código /pandas/io/json/_json.py , de forma predeterminada, el número entero de precision es de hasta 10 , consulte la siguiente información de la base de código.

 def to_json( path_or_buf, obj, orient: Optional[str] = None, date_format: str = "epoch", double_precision: int = 10, force_ascii: bool = True, date_unit: str = "ms", default_handler: Optional[Callable[[Any], JSONSerializable]] = None, lines: bool = False, compression: Optional[str] = "infer", index: bool = True, indent: int = 0,

Si aplica la precisión máxima entonces, estará debajo.

 >>> print(df.to_json(indent=2, orient='records', double_precision=15)) [ { "0":0.0000000112345, "1":0.00000000112345, "2":0.000000000112345, "3":0.000000000011234, "4":0.000000000001123, "5":0.000000000000112, "6":0.000000000000011, "7":0.000000000000001, "8":1.12345e-16, "9":1.12345e-17, "10":1.12345e-18, "11":1.12345e-19, "12":1.12345e-20, "13":1.12345e-21, "14":1.12345e-22, "15":1.12345e-23, "16":1.12345e-24, "17":1.12345e-25, "18":1.12345e-26, "19":1.12345e-27, "20":1.12345e-28, "21":1.12345e-29, "22":1.12345e-30, "23":1.12345e-31, "24":1.12345e-32, "25":1.12345e-33, "26":1.12345e-34, "27":1.12345e-35, "28":1.12345e-36, "29":1.12345e-37, "30":1.12345e-38, "31":1.12345e-39 } ]

Nota: obtendrá un error de valor si usa precision superior a 15.

 ValueError: Invalid value '20' for option 'double_precision', max is '15'

Entonces, en cierto sentido, esto no es lo mismo que json.dumps .

over 4 years ago · Santiago Trujillo Report

0

No estoy seguro de lograr esto con pd.DataFrame.to_json , pero podemos usar pd.DataFrame.to_dict , json y pd.read_json para lograr una representación json de precisión completa a partir de un marco de datos de pandas.

 json_df = json.dumps(df.to_dict('index'), indent=2) >>> print(json_df) { "0": { "0": 1.12345e-08, "1": 1.12345e-09, "2": 1.12345e-10, "3": 1.12345e-11, "4": 1.12345e-12, "5": 1.12345e-13, "6": 1.12345e-14, "7": 1.12345e-15, "8": 1.12345e-16, "9": 1.12345e-17, "10": 1.12345e-18, "11": 1.12345e-19 } }

Para volver a leerlo, podemos hacer:

 >>> pd.read_json(json_df, orient='index') 0 1 2 ... 9 10 11 0 1.123450e-08 1.123450e-09 1.123450e-10 ... 1.123450e-17 1.123450e-18 1.123450e-19 [1 rows x 12 columns]
over 4 years ago · Santiago Trujillo Report

0

pd.DataFrame.to_json usa la biblioteca interna pandas._libs.json y no un módulo json estándar. Esto explica la diferencia de comportamiento. El primero "normaliza" los números internamente y no expone la API para controlarlo. Como resultado, tiene las siguientes opciones:

Convierta a diccionario y descargue utilizando la biblioteca json estándar (como se mencionó anteriormente):

 >>> print(json.dumps(df.to_dict(orient='records'), indent=2)) [ { "0": 1.12345e-08, "1": 1.12345e-09, "2": 1.12345e-10, "3": 1.12345e-11, "4": 1.12345e-12, "5": 1.12345e-13, "6": 1.12345e-14, "7": 1.12345e-15, "8": 1.12345e-16, "9": 1.12345e-17, "10": 1.12345e-18, "11": 1.12345e-19 } ]

Esta es una solución perfectamente legítima.

Puede usar el formato CSV en lugar de JSON y especificar el formato de punto flotante deseado:

 >>> print(df.to_csv(float_format='%.10e', index=False)) 0,1,2,3,4,5,6,7,8,9,10,11 1.1234500000e-08,1.1234500000e-09,1.1234500000e-10,1.1234500000e-11,1.1234500000e-12,1.1234500000e-13,1.1234500000e-14,1.1234500000e-15,1.1234500000e-16,1.1234500000e-17,1.1234500000e-18,1.1234500000e-19

Otra opción es convertir los valores en cadenas antes de que se active la "normalización":

 >>> print(df.astype(str).to_json(indent=2, orient='index')) { "0":{ "0":"1.12345e-08", "1":"1.12345e-09", "2":"1.12345e-10", "3":"1.12345e-11", "4":"1.12345e-12", "5":"1.12345e-13", "6":"1.12345e-14", "7":"1.12345e-15", "8":"1.12345e-16", "9":"1.12345e-17", "10":"1.12345e-18", "11":"1.12345e-19" } }

La conversión a cadena requerirá atención especial al leer el JSON.

Y finalmente, si necesita los valores exactos, simplemente use formato binario como parquet o pickle .

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!