es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo crear una tupla de row[colname] a partir de df.iterrows() basado en un diccionario

Estoy tratando de crear una tupla que se base en un diccionario de nombres de columnas df para pasar por mi cursor cuando se insertan datos en una base de datos.

Imagina un df con 3 columnas:
colA colB colC
1awf pref 02-03-2021
2fef cpvd 02-02-2021
3ace pfva 02-05-2021
4cat raof 01-03-2021
5agt btoa 04-01-2021

Y un diccionario que creé para definir los tipos de datos de cada columna en el df:
coldict =
{‘colA’:’varchar(4)’,
‘colB’:’varchar(4)’,
‘colC’:’date’}

Normalmente, la declaración del cursor que usaría para insertar este dataframe en una tabla de base de datos (llamada tabla_A aquí) se vería así:
for i,r in df.iterrows():
cursor.execute(
‘INSERT INTO table_A(
[colA],[colB],[colC]) VALUES (?,?,?)’,
(row[‘colA’],row[‘colB’],row[‘colC’]))

Ahora imagina si la tabla tuviera 40 columnas en lugar de 3. ¡Eso es mucho escribir! Me pregunto si es posible hacer esta declaración más dinámica en una función, donde pasaría el diccionario y lo recorrería para crear las mismas 2 partes de la declaración cursor.execute. La declaración INSERT es bastante sencilla, y simplemente recorrí las claves del diccionario de coldict para eso y concatené las cadenas. El número de signos de interrogación a pasar también es bastante fácil, ya que solo es la longitud de las claves del diccionario. Sin embargo, tengo problemas para hacer lo mismo con la segunda parte, es decir, (row[‘colA’],row[‘colB’],row[‘colC’])… ¿es eso posible? La salida final deseada se vería así:

def datadump(df, insert_statement, rep_qs, df_cols):
for i,r in df.iterrows():
cursor.execute(
insert_statement) VALUES (rep_qs)’,
df_cols)
donde solo necesito una forma de crear dinámicamente la tupla que es df_cols. ¡Espero que esto tenga sentido! ¡Gracias!

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible crear la tupla dinamicamente basada en el diccionario de nombres de columna y tipos de datos. Puedes usar la función zip() para crear pares de (nombre de columna, valor) para cada fila en el dataframe, y luego usar una comprensión de lista para extraer los valores para cada columna basándote en las claves del diccionario. Aquí tienes un ejemplo de implementación de la función datadump() utilizando este enfoque:

    def datadump(df, insert_statement, rep_qs, col_dict):
        cols = list(col_dict.keys())  # obtener los nombres de las columnas del diccionario
        for _, row in df.iterrows():
            # crear una lista de pares (nombre de columna, valor) para la fila actual
            col_values = [(col, row[col]) for col in cols]
            # extraer los valores para cada columna basándote en las claves del diccionario
            values = [row[col] for col in cols]
            cursor.execute(
                f"{insert_statement} ({rep_qs})",
                values
            )
    

    Luego puedes llamar a esta función con el dataframe, la sentencia de inserción (con espacios reservados para los valores), la cadena que se repetirá para cada espacio reservado de valor y el diccionario de nombres de columna y tipos de datos:

    datadump(df, "INSERT INTO table_A ([colA], [colB], [colC]) VALUES", "?, ?, ?", coldict)
    

    Esto debería funcionar para cualquier cantidad de columnas en el dataframe y cualquier tipo de dato de columna en el diccionario.

Comments are closed.