Cómo hacer buenos ejemplos de pandas reproducibles

221

Habiendo pasado una cantidad de tiempo decente viendo ambos y En SO, la impresión que obtengo es que pandases menos probable que las preguntas contengan datos reproducibles. Esto es algo que la comunidad R ha sido muy buena para alentar, y gracias a guías como esta , los recién llegados pueden obtener ayuda para armar estos ejemplos. Las personas que pueden leer estas guías y regresar con datos reproducibles a menudo tendrán mucha mejor suerte al obtener respuestas a sus preguntas.

¿Cómo podemos crear buenos ejemplos reproducibles para pandaspreguntas? Se pueden juntar marcos de datos simples, por ejemplo:

import pandas as pd
df = pd.DataFrame({'user': ['Bob', 'Jane', 'Alice'], 
                   'income': [40000, 50000, 42000]})

Pero muchos conjuntos de datos de ejemplo necesitan una estructura más complicada, por ejemplo:

  • datetime índices o datos
  • Múltiples variables categóricas (¿hay un equivalente a la expand.grid()función de R , que produce todas las combinaciones posibles de algunas variables dadas?)
  • MultiIndex o Panel de datos

Para conjuntos de datos que son difíciles de simular usando algunas líneas de código, ¿hay un equivalente a R dput()que le permita generar código que se pueda copiar y pegar para regenerar su estructura de datos?

Mario
fuente
8
Si copia el resultado de la impresión, la mayoría de las veces los respondedores pueden usar read_clipboard () ... excepto MultiIndex: s. Dicho esto, dict es una buena adición
Andy Hayden
8
Además de lo que dijo Andy, creo que el pegado de copias df.head(N).to_dict(), donde Nhay un número razonable, es una buena manera de hacerlo. Bonus + 1 para agregar saltos de línea bonita a la salida. Para las marcas de tiempo, generalmente solo necesitará agregar from pandas import Timestampal principio del código.
Paul H

Respuestas:

323

Nota: Las ideas aquí son bastante genéricas para Stack Overflow, de hecho preguntas .

Descargo de responsabilidad: escribir una buena pregunta es DURO.

El bueno:

  • incluya un pequeño * DataFrame de ejemplo, ya sea como código ejecutable:

    In [1]: df = pd.DataFrame([[1, 2], [1, 3], [4, 6]], columns=['A', 'B'])

    o hacerlo "copiar y pegar" usando pd.read_clipboard(sep='\s\s+'), puede formatear el texto para resaltar el desbordamiento de pila y usar Ctrl+ K(o anteponer cuatro espacios a cada línea), o colocar tres tildes arriba y abajo de su código con su código sin sangría:

    In [2]: df
    Out[2]: 
       A  B
    0  1  2
    1  1  3
    2  4  6
    

    pd.read_clipboard(sep='\s\s+')ponte a prueba

    * Realmente media pequeña , la gran mayoría de las tramas de datos de ejemplo podría ser menos de 6 filas cita requerida , y apuesto a que puedo hacerlo en 5 filas. ¿Puede reproducir el error con df = df.head(), si no jugar, para ver si puede hacer un pequeño DataFrame que muestre el problema que enfrenta?

    * Cada regla tiene una excepción, la más obvia es para problemas de rendimiento ( en cuyo caso, sin duda utilizar% timeit y posiblemente% prun ), donde se debe generar (np.random.seed considerar el uso de lo que tenemos exactamente el mismo marco): df = pd.DataFrame(np.random.randn(100000000, 10)). Decir que "hacer que este código sea rápido para mí" no es estrictamente el tema del sitio ...

  • escriba el resultado que desea (de manera similar a lo anterior)

    In [3]: iwantthis
    Out[3]: 
       A  B
    0  1  5
    1  4  6
    

    Explica de dónde provienen los números: el 5 es la suma de la columna B para las filas donde A es 1.

  • muestra el código que has probado:

    In [4]: df.groupby('A').sum()
    Out[4]: 
       B
    A   
    1  5
    4  6
    

    Pero diga qué es incorrecto: la columna A está en el índice en lugar de una columna.

  • demuestre que ha investigado un poco ( busque en los documentos , busque StackOverflow ), brinde un resumen:

    La cadena de documentación para la suma simplemente indica "Calcular suma de valores de grupo"

    Los documentos de groupby no dan ningún ejemplo de esto.

    Aparte: la respuesta aquí es usar df.groupby('A', as_index=False).sum().

  • si es relevante que tengas columnas de marca de tiempo, por ejemplo, si estás remuestreando o algo así, entonces sé explícito y aplícalo pd.to_datetimecomo medida **.

    df['date'] = pd.to_datetime(df['date']) # this column ought to be date..

    ** A veces este es el problema en sí: eran cadenas.

El malo:

  • no incluye un MultiIndex, que no podemos copiar y pegar (ver arriba), esto es una queja con la visualización predeterminada de los pandas pero molesta:

    In [11]: df
    Out[11]:
         C
    A B   
    1 2  3
      2  6
    

    La forma correcta es incluir un DataFrame ordinario con una set_indexllamada:

    In [12]: df = pd.DataFrame([[1, 2, 3], [1, 2, 6]], columns=['A', 'B', 'C']).set_index(['A', 'B'])
    
    In [13]: df
    Out[13]: 
         C
    A B   
    1 2  3
      2  6
    
  • proporcione una idea de lo que es cuando da el resultado que desea:

       B
    A   
    1  1
    5  0
    

    Sea específico sobre cómo obtuvo los números (qué son) ... verifique que sean correctos.

  • Si su código arroja un error, incluya todo el seguimiento de la pila (esto se puede editar más adelante si es demasiado ruidoso). Muestre el número de línea (y la línea correspondiente de su código contra el cual está aumentando).

El feo:

  • no enlace a un csv al que no tengamos acceso (idealmente no enlace a una fuente externa en absoluto ...)

    df = pd.read_csv('my_secret_file.csv')  # ideally with lots of parsing options

    La mayoría de los datos son propietarios , obtenemos eso: invente datos similares y vea si puede reproducir el problema (algo pequeño).

  • no explique la situación vagamente en palabras, como si tuviera un DataFrame que es "grande", mencione algunos de los nombres de columna al pasar (asegúrese de no mencionar sus tipos). Intenta entrar en muchos detalles sobre algo que no tiene sentido sin ver el contexto real. Presumiblemente, nadie va a leer hasta el final de este párrafo.

    Los ensayos son malos, es más fácil con pequeños ejemplos.

  • no incluya 10+ (100+ ??) líneas de mezcla de datos antes de llegar a su pregunta real.

    Por favor, vemos suficiente de esto en nuestros trabajos diarios. Queremos ayudar, pero no como esto ... .
    Corte la introducción y solo muestre los DataFrames relevantes (o versiones pequeñas de ellos) en el paso que le está causando problemas.

De todos modos, ¡diviértete aprendiendo Python, NumPy y Pandas!

Andy Hayden
fuente
30
+1 por la pd.read_clipboard(sep='\s\s+')propina. Cuando publico preguntas SO que necesitan un marco de datos especial pero fácil de compartir, como este, lo construyo en Excel, lo copio a mi portapapeles y luego le indico a SOers que haga lo mismo. ¡Ahorra mucho tiempo!
zelusp
1
la pd.read_clipboard(sep='\s\s+')sugerencia no parece funcionar si está utilizando Python en un servidor remoto, que es donde viven muchos conjuntos de datos grandes.
user5359531
1
¿Por qué pd.read_clipboard(sep='\s\s+'), y no es más simple pd.read_clipboard()(con el valor predeterminado ‘s+’)? El primero necesita al menos 2 caracteres de espacio en blanco, lo que puede causar problemas si solo hay 1 (por ejemplo, ver esto en la respuesta de @JohnE ).
MarianD
3
@MarianD la razón por la que \ s \ s + es tan popular es que a menudo hay uno, por ejemplo, en el nombre de una columna, pero el múltiple es más raro, y la salida de pandas se coloca muy bien en al menos dos entre columnas. Dado que esto es solo para juguetes / pequeños conjuntos de datos, es bastante poderoso / la mayoría de los casos. Nota: las pestañas separadas serían una historia diferente, aunque stackoverflow reemplaza las pestañas con espacios, pero si tiene un tsv, simplemente use \ t.
Andy Hayden
3
Uf, siempre uso pd.read_clipboard(), cuando hay espacios, lo hago pd.read_clipboard(sep='\s+{2,}', engine='python'):: P
U10-Adelante
72

Cómo crear conjuntos de datos de muestra

Esto es principalmente para ampliar la respuesta de @ AndyHayden al proporcionar ejemplos de cómo puede crear marcos de datos de muestra. Los pandas y (especialmente) numpy le brindan una variedad de herramientas para esto, de modo que generalmente puede crear un facsímil razonable de cualquier conjunto de datos real con solo unas pocas líneas de código.

Después de importar numpy y pandas, asegúrese de proporcionar una semilla aleatoria si desea que las personas puedan reproducir exactamente sus datos y resultados.

import numpy as np
import pandas as pd

np.random.seed(123)

Un ejemplo de fregadero de cocina

Aquí hay un ejemplo que muestra una variedad de cosas que puede hacer. Se podrían crear todo tipo de marcos de datos de muestra útiles a partir de un subconjunto de esto:

df = pd.DataFrame({ 

    # some ways to create random data
    'a':np.random.randn(6),
    'b':np.random.choice( [5,7,np.nan], 6),
    'c':np.random.choice( ['panda','python','shark'], 6),

    # some ways to create systematic groups for indexing or groupby
    # this is similar to r's expand.grid(), see note 2 below
    'd':np.repeat( range(3), 2 ),
    'e':np.tile(   range(2), 3 ),

    # a date range and set of random dates
    'f':pd.date_range('1/1/2011', periods=6, freq='D'),
    'g':np.random.choice( pd.date_range('1/1/2011', periods=365, 
                          freq='D'), 6, replace=False) 
    })

Esto produce:

          a   b       c  d  e          f          g
0 -1.085631 NaN   panda  0  0 2011-01-01 2011-08-12
1  0.997345   7   shark  0  1 2011-01-02 2011-11-10
2  0.282978   5   panda  1  0 2011-01-03 2011-10-30
3 -1.506295   7  python  1  1 2011-01-04 2011-09-07
4 -0.578600 NaN   shark  2  0 2011-01-05 2011-02-27
5  1.651437   7  python  2  1 2011-01-06 2011-02-03

Algunas notas:

  1. np.repeaty np.tile(columnas dy e) son muy útiles para crear grupos e índices de una manera muy regular. Para 2 columnas, esto se puede utilizar para duplicar fácilmente r's expand.grid()pero también es más flexible en la capacidad de proporcionar un subconjunto de todas las permutaciones. Sin embargo, para 3 o más columnas, la sintaxis se vuelve rápidamente difícil de manejar.
  2. Para un reemplazo más directo de los r, expand.grid()vea la itertoolssolución en el libro de cocina de los pandas o la np.meshgridsolución que se muestra aquí . Esos permitirán cualquier cantidad de dimensiones.
  3. Puedes hacer bastante con np.random.choice. Por ejemplo, en la columna g, tenemos una selección aleatoria de 6 fechas de 2011. Además, al establecer replace=Falsepodemos asegurar que estas fechas son únicas, muy útiles si queremos usar esto como un índice con valores únicos.

Datos falsos del mercado de valores

Además de tomar subconjuntos del código anterior, puede combinar aún más las técnicas para hacer casi cualquier cosa. Por ejemplo, aquí hay un breve ejemplo que combina np.tiley date_rangecrea datos de muestra para 4 acciones que cubren las mismas fechas:

stocks = pd.DataFrame({ 
    'ticker':np.repeat( ['aapl','goog','yhoo','msft'], 25 ),
    'date':np.tile( pd.date_range('1/1/2011', periods=25, freq='D'), 4 ),
    'price':(np.random.randn(100).cumsum() + 10) })

Ahora tenemos un conjunto de datos de muestra con 100 líneas (25 fechas por ticker), pero solo hemos usado 4 líneas para hacerlo, lo que facilita la reproducción de todos los demás sin copiar y pegar 100 líneas de código. Luego puede mostrar subconjuntos de datos si esto ayuda a explicar su pregunta:

>>> stocks.head(5)

        date      price ticker
0 2011-01-01   9.497412   aapl
1 2011-01-02  10.261908   aapl
2 2011-01-03   9.438538   aapl
3 2011-01-04   9.515958   aapl
4 2011-01-05   7.554070   aapl

>>> stocks.groupby('ticker').head(2)

         date      price ticker
0  2011-01-01   9.497412   aapl
1  2011-01-02  10.261908   aapl
25 2011-01-01   8.277772   goog
26 2011-01-02   7.714916   goog
50 2011-01-01   5.613023   yhoo
51 2011-01-02   6.397686   yhoo
75 2011-01-01  11.736584   msft
76 2011-01-02  11.944519   msft
JohnE
fuente
2
Gran respuesta. Después de escribir esta pregunta, en realidad escribí una implementación muy corta y simple expand.grid()que está incluida en el libro de cocina de los pandas , también podría incluirla en su respuesta. Su respuesta muestra cómo crear conjuntos de datos más complejos de lo que expand_grid()podría manejar mi función, lo cual es genial.
Marius
46

Diario de un respondedor

Mi mejor consejo para hacer preguntas sería jugar con la psicología de las personas que responden preguntas. Al ser una de esas personas, puedo dar una idea de por qué respondo ciertas preguntas y por qué no respondo otras.

Motivaciones

Estoy motivado para responder preguntas por varias razones

  1. Stackoverflow.com ha sido un recurso tremendamente valioso para mí. Yo quería devolver.
  2. En mis esfuerzos por retribuir, he encontrado que este sitio es un recurso aún más poderoso que antes. Responder preguntas es una experiencia de aprendizaje para mí y me gusta aprender. Lea esta respuesta y comente de otro veterinario . Este tipo de interacción me hace feliz.
  3. Me gustan los puntos!
  4. Ver # 3.
  5. Me gustan los problemas interesantes

Todas mis intenciones más puras son geniales, pero obtengo esa satisfacción si respondo 1 pregunta o 30. Lo que impulsa mis elecciones para qué preguntas responder tiene un gran componente de maximización de puntos.

También dedicaré tiempo a problemas interesantes, pero eso es poco y distante entre sí y no ayuda a quien pregunta y necesita una solución a una pregunta no interesante. Su mejor apuesta para que responda una pregunta es responderla en un plato maduro para que pueda responderla con el menor esfuerzo posible. Si estoy viendo dos preguntas y una tiene código, puedo copiar y pegar para crear todas las variables que necesito ... ¡Estoy tomando esa! Volveré al otro si tengo tiempo, tal vez.

Consejo principal

Facilite a las personas que responden preguntas.

  • Proporcione código que cree las variables que se necesitan.
  • Minimiza ese código. Si mis ojos se vuelven vidriosos mientras miro la publicación, voy a la siguiente pregunta o vuelvo a lo que sea que esté haciendo.
  • Piensa en lo que estás preguntando y sé específico. Queremos ver lo que has hecho porque los idiomas naturales (inglés) son inexactos y confusos. Los ejemplos de código de lo que ha intentado ayudan a resolver inconsistencias en una descripción de lenguaje natural.
  • ¡POR FAVOR muestre lo que espera! Tengo que sentarme y probar cosas. Casi nunca sé la respuesta a una pregunta sin probar algunas cosas. Si no veo un ejemplo de lo que estás buscando, podría pasar la pregunta porque no tengo ganas de adivinar.

Su reputación es más que solo su reputación.

Me gustan los puntos (lo mencioné anteriormente). Pero esos puntos no son realmente mi reputación. Mi verdadera reputación es una amalgama de lo que otros en el sitio piensan de mí. Me esfuerzo por ser justo y honesto y espero que otros puedan ver eso. Lo que eso significa para un autor de la pregunta es que recordamos los comportamientos de los participantes. Si no selecciona respuestas y vota buenas respuestas, lo recuerdo. Si te comportas de una manera que no me gusta o de una forma que me gusta, lo recuerdo. Esto también juega a qué preguntas responderé.


De todos modos, probablemente pueda continuar, pero les perdonaré a todos los que realmente leen esto.

piRSquared
fuente
26

El desafío Uno de los aspectos más difíciles de responder a las preguntas de SO es el tiempo que lleva recrear el problema (incluidos los datos). Las preguntas que no tienen una forma clara de reproducir los datos tienen menos probabilidades de ser respondidas. Dado que se está tomando el tiempo para escribir una pregunta y tiene un problema con el que le gustaría recibir ayuda, puede ayudarse fácilmente al proporcionar datos que otros pueden usar para ayudar a resolver su problema.

Las instrucciones proporcionadas por @Andy para escribir buenas preguntas de Pandas son un excelente lugar para comenzar. Para obtener más información, consulte cómo preguntar y cómo crear ejemplos mínimos, completos y verificables .

Indique claramente su pregunta por adelantado. Después de tomarse el tiempo para escribir su pregunta y cualquier código de muestra, intente leerlo y proporcione un 'Resumen Ejecutivo' para su lector que resuma el problema y que establezca claramente la pregunta.

Pregunta original :

Tengo estos datos ...

Quiero hacer esto...

Quiero que mi resultado se vea así ...

Sin embargo, cuando trato de hacer [esto], me sale el siguiente problema ...

He tratado de encontrar soluciones haciendo [esto] y [eso].

¿Cómo lo soluciono?

Dependiendo de la cantidad de datos, código de muestra y pilas de errores proporcionados, el lector debe recorrer un largo camino antes de comprender cuál es el problema. Intente volver a plantear su pregunta para que la pregunta esté en la parte superior y luego proporcione los detalles necesarios.

Pregunta revisada :

Qustion: ¿Cómo puedo hacer [esto]?

He tratado de encontrar soluciones haciendo [esto] y [eso].

Cuando intenté hacer [esto], me sale el siguiente problema ...

Me gustaría que mis resultados finales se vean así ...

Aquí hay un código mínimo que puede reproducir mi problema ...

Y aquí está cómo recrear mis datos de muestra: df = pd.DataFrame({'A': [...], 'B': [...], ...})

PROPORCIONE DATOS DE MUESTRA SI ES NECESARIO !!!

A veces, solo la cabeza o la cola del DataFrame es todo lo que se necesita. También puede usar los métodos propuestos por @JohnE para crear conjuntos de datos más grandes que otros puedan reproducir. Usando su ejemplo para generar un DataFrame de 100 filas de precios de acciones:

stocks = pd.DataFrame({ 
    'ticker':np.repeat( ['aapl','goog','yhoo','msft'], 25 ),
    'date':np.tile( pd.date_range('1/1/2011', periods=25, freq='D'), 4 ),
    'price':(np.random.randn(100).cumsum() + 10) })

Si estos fueron sus datos reales, es posible que desee incluir el encabezado y / o la cola del marco de datos de la siguiente manera (asegúrese de anonimizar los datos confidenciales):

>>> stocks.head(5).to_dict()
{'date': {0: Timestamp('2011-01-01 00:00:00'),
  1: Timestamp('2011-01-01 00:00:00'),
  2: Timestamp('2011-01-01 00:00:00'),
  3: Timestamp('2011-01-01 00:00:00'),
  4: Timestamp('2011-01-02 00:00:00')},
 'price': {0: 10.284260107718254,
  1: 11.930300761831457,
  2: 10.93741046217319,
  3: 10.884574289565609,
  4: 11.78005850418319},
 'ticker': {0: 'aapl', 1: 'aapl', 2: 'aapl', 3: 'aapl', 4: 'aapl'}}

>>> pd.concat([stocks.head(), stocks.tail()], ignore_index=True).to_dict()
{'date': {0: Timestamp('2011-01-01 00:00:00'),
  1: Timestamp('2011-01-01 00:00:00'),
  2: Timestamp('2011-01-01 00:00:00'),
  3: Timestamp('2011-01-01 00:00:00'),
  4: Timestamp('2011-01-02 00:00:00'),
  5: Timestamp('2011-01-24 00:00:00'),
  6: Timestamp('2011-01-25 00:00:00'),
  7: Timestamp('2011-01-25 00:00:00'),
  8: Timestamp('2011-01-25 00:00:00'),
  9: Timestamp('2011-01-25 00:00:00')},
 'price': {0: 10.284260107718254,
  1: 11.930300761831457,
  2: 10.93741046217319,
  3: 10.884574289565609,
  4: 11.78005850418319,
  5: 10.017209045035006,
  6: 10.57090128181566,
  7: 11.442792747870204,
  8: 11.592953372130493,
  9: 12.864146419530938},
 'ticker': {0: 'aapl',
  1: 'aapl',
  2: 'aapl',
  3: 'aapl',
  4: 'aapl',
  5: 'msft',
  6: 'msft',
  7: 'msft',
  8: 'msft',
  9: 'msft'}}

Es posible que también desee proporcionar una descripción del DataFrame (utilizando solo las columnas relevantes). Esto facilita que otros verifiquen los tipos de datos de cada columna e identifiquen otros errores comunes (por ejemplo, fechas como cadena frente a fecha y hora 64 frente a objeto):

stocks.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 100 entries, 0 to 99
Data columns (total 3 columns):
date      100 non-null datetime64[ns]
price     100 non-null float64
ticker    100 non-null object
dtypes: datetime64[ns](1), float64(1), object(1)

NOTA: Si su DataFrame tiene un MultiIndex:

Si su DataFrame tiene un índice múltiple, primero debe reiniciar antes de llamar to_dict. Luego debe volver a crear el índice con set_index:

# MultiIndex example.  First create a MultiIndex DataFrame.
df = stocks.set_index(['date', 'ticker'])
>>> df
                       price
date       ticker           
2011-01-01 aapl    10.284260
           aapl    11.930301
           aapl    10.937410
           aapl    10.884574
2011-01-02 aapl    11.780059
...

# After resetting the index and passing the DataFrame to `to_dict`, make sure to use 
# `set_index` to restore the original MultiIndex.  This DataFrame can then be restored.

d = df.reset_index().to_dict()
df_new = pd.DataFrame(d).set_index(['date', 'ticker'])
>>> df_new.head()
                       price
date       ticker           
2011-01-01 aapl    10.284260
           aapl    11.930301
           aapl    10.937410
           aapl    10.884574
2011-01-02 aapl    11.780059
Alejandro
fuente
12

Aquí está mi versión de dput- la herramienta estándar R para producir informes reproducibles - para Pandas DataFrames. Probablemente fallará para marcos más complejos, pero parece hacer el trabajo en casos simples:

import pandas as pd
def dput (x):
    if isinstance(x,pd.Series):
        return "pd.Series(%s,dtype='%s',index=pd.%s)" % (list(x),x.dtype,x.index)
    if isinstance(x,pd.DataFrame):
        return "pd.DataFrame({" + ", ".join([
            "'%s': %s" % (c,dput(x[c])) for c in x.columns]) + (
                "}, index=pd.%s)" % (x.index))
    raise NotImplementedError("dput",type(x),x)

ahora,

df = pd.DataFrame({'a':[1,2,3,4,2,1,3,1]})
assert df.equals(eval(dput(df)))
du = pd.get_dummies(df.a,"foo")
assert du.equals(eval(dput(du)))
di = df
di.index = list('abcdefgh')
assert di.equals(eval(dput(di)))

Tenga en cuenta que esto produce un resultado mucho más detallado que DataFrame.to_dict, por ejemplo,

pd.DataFrame({
  'foo_1':pd.Series([1, 0, 0, 0, 0, 1, 0, 1],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_2':pd.Series([0, 1, 0, 0, 1, 0, 0, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_3':pd.Series([0, 0, 1, 0, 0, 0, 1, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_4':pd.Series([0, 0, 0, 1, 0, 0, 0, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1))},
  index=pd.RangeIndex(start=0, stop=8, step=1))

vs

{'foo_1': {0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1, 6: 0, 7: 1}, 
 'foo_2': {0: 0, 1: 1, 2: 0, 3: 0, 4: 1, 5: 0, 6: 0, 7: 0}, 
 'foo_3': {0: 0, 1: 0, 2: 1, 3: 0, 4: 0, 5: 0, 6: 1, 7: 0}, 
 'foo_4': {0: 0, 1: 0, 2: 0, 3: 1, 4: 0, 5: 0, 6: 0, 7: 0}}

para duarriba, pero conserva los tipos de columna . Por ejemplo, en el caso de prueba anterior,

du.equals(pd.DataFrame(du.to_dict()))
==> False

porque du.dtypeses uint8y pd.DataFrame(du.to_dict()).dtypeses int64.

sds
fuente
es más claro, aunque admito que no veo por qué querría usarloto_dict
Paul H
2
Porque conserva los tipos de columna. Más específicamente du.equals(eval(dput(df))),.
sds