Python 关于np.nan和None的区别和导入数据库的注意事项

工作中遇到这样的场景:

把数据从生产环境以csv导出来后,要手工导入测试环境的mysql数据库。直接在mysql里导数的话,如果数据量大会非常慢,而且不稳定。写一个python脚本自动导数是最方便的,但要满足几个需求:

1.csv格式导出来的数据,数据库里如果是空值会变成N。但在mysql里我希望它还是空值null;

2.导入mysql的数据,希望能保留两位小数。

1和2要结合起来看,其实就是替换'N‘的同时做一些数据处理,需要注意的是python里数据类型的问题。

思路是:1.先把N变为np.nan;2.将字段类型转为float做处理;3;把nan再转为None塞入数据库

 

这样做的原因是:

numpy和pandas能处理NaN,但是如果遇到None就会报错,所以在数据处理阶段用np.nan

None能够直接被导入数据库作为空值处理, 但包含NaN的数据导入时会报错。

 

导入数据的那些基本操作就不写了,主要的代码为

data.replace('N',np.nan,inplace=True)  #将N替换为np.nan,处理完后所有的N变为NaN了

formater="{0:.02f}".format
data['index_val'] = data['index_val'].astype('float').apply(formater) #字段改为float后保留两位小数
#注意如果这时候打印data,会发现index_val那一列的空值变为nan,其余列的空值还是NaN。data.info()会发现所有字段都变成object
   
data.replace('nan','nullvalue',inplace=True)
data.replace('nullvalue',np.nan,inplace=True) 

data = data.where(data.notnull(),None)

这里需要注意的是直接把index_val列的nan替换成None是不管用的,比较奇怪的是处理后的数据nan跟别的列中NaN还不一样,用s.where(s.notnull(),None)直接转None能应用在别的列,但在数据处理后的index_val列完全不起作用,还是讨厌的nan。看数据类型现在都是object于是想了一个办法,先把index_val列的nan变成“正常”的np.nan:将它先替换成一个字符串,再统一改为None就可以了。

 

当然也可以在插入数据库的时候替换一下也行,这样就不是在pandas里改了,是在数组里替换:

data_placeholder = ["%s"] * len(select_columns)
insert_sql = f'''insert into {tablename} ({",".join(select_columns)}) values({",".join(data_placeholder)})'''

cursor.executemany(insert_sql, [ [None if str(element)=='nan' else element for element in ele ] for ele in select_data.values.tolist()])

conn.commit()

 

你可能感兴趣的:(Python,Mysql)