Как изменить тип данных при создании SQL таблицы из DataFrame?
Хочу из DataFrame создать таблицу в SQL кодом ниже.
Таблица создаётся, но типы данных у этой таблицы не такие как мне хотелось бы. Столбцы у меня создаются под типом данных: bigint, text, а нужны int, varchar. Пробую методом dtype={} указать нужные мне типы данных, но таблица создаётся со всё теми же данными biging, text.
with ftp_client.open("/home/20211027165128-41.zip","r", bufsize=32768) as f:
archive = zipfile.ZipFile(f, 'r')
df = pd.read_csv(io.BytesIO(archive.read('GExternalGsmCell.csv')))
df.to_sql('ZTE_GExternalGsmCell', con=connSQLBD_vf_work, schema='art',
if_exists='replace',
dtype={'datefld': sqlalchemy.DateTime(),
'intfld': sqlalchemy.types.INTEGER(),
'strfld': sqlalchemy.types.VARCHAR(length=255),
'floatfld': sqlalchemy.types.Float(precision=3, asdecimal=True),
'bigint': sqlalchemy.types.INT(),
'text': sqlalchemy.types.VARCHAR(length=255),
'booleanfld': sqlalchemy.types.Boolean})
Ответы (2 шт):
Скорее всего проблема в несоответствии имен столбцов фрейма и ключей словаря, который вы передаете в параметр dtype. Например если у вас столбцы в upper case или mixed case, то и в параметре dtype они должны точно соответствовать именам столбцов фрейма.
Для простоты можно явно преобразовать все имена столбцов в DataFrame'е в lower case:
df.columns = df.columns.str.lower()
В параметр dtype при вызове DataFrame.to_sql(..., dtype={...}) нужно передавать словарь с точными именами столбцов DataFrame в виде ключей:
dtype = {
"df_column_1_exact_name": sqlalchemy.types.INTEGER(),
"df_column_3_exact_name": sqlalchemy.types.INTEGER(),
"df_column_N_exact_name": sqlalchemy.types.VARCHAR(length=255),
}
df.to_sql("table_name", con=db_conn, dtype=dtype)
PS в dtype не обязательно передавать все имена столбцов - достаточно только тех, которые мы хотим задать явно.
Нашёл способ на сайте https://russianblogs.com/article/91571572655/ )
В нём создается функция def mapping_df_types(df) которая проходиться по первой строке каждого столбца и создаёт словарь для замены типа данных функцией dtype. Если строка относиться к типу данных object - она заменяет её на тип данных VARCHAR, если у строки тип данных int,float - заменяет на Float, Integer
def mapping_df_types(df):
dtypedict = {}
for i, j in zip(df.columns, df.dtypes):
if "object" in str(j):
dtypedict.update({i: sqlalchemy.types.NVARCHAR(length=255)})
if "float" in str(j):
dtypedict.update({i: sqlalchemy.types.Float(precision=2, asdecimal=True)})
if "int" in str(j):
dtypedict.update({i: sqlalchemy.types.Integer()})
return dtypedict
with ftp_client.open("/home/20211027165128-41.zip","r", bufsize=32768) as f:
archive = zipfile.ZipFile(f, 'r')
df = pd.read_csv(io.BytesIO(archive.read('GExternalGsmCell.csv')))
dtypedict = mapping_df_types(df)
df.to_sql('ZTE_GExternalGsmCell', con=connSQLBD_vf_work, schema='art', if_exists='replace',dtype=dtypedict)