pandas 如何将缺少值的列转换为字符串?

57hvy0tb  于 2023-02-07  发布在  其他
关注(0)|答案(2)|浏览(140)

我需要使用SQL Alchemy从Pandas导出一个 Dataframe 到Microsoft SQL Server。许多列是字符串,有缺失的值和一些很长的整数,例如999999999999999999999999999999。这些数字是某种外键,所以值本身没有任何意义,所以我可以将它们转换为字符串。
尝试导出到SQL时,这会导致SQL Alchemy中出现以下错误:

OverflowError: int too big to convert

我尝试用astype(str)转换为字符串,但随后遇到了这样的问题:标识为nans的缺失值被转换为字符串'nan' -因此SQL不会将它们视为null,而是视为字符串'nan'。

**我找到的唯一解决方案是先转换为str,然后用numpy.nan替换'nan'。有更好的方法吗?**这很麻烦,相对较慢,而且非常复杂:首先,我将所有内容转换为string,这个转换将null转换为string,然后我将它们转换为NaN,NaN只能是浮点型,最后得到一个混合类型的列。

还是我只能忍气吞声,接受Pandas在处理缺失值方面很糟糕的事实?
我有一个例子如下:

import numpy as np, pandas as pd, time

from sqlalchemy import create_engine, MetaData, Table, select
import sqlalchemy as sqlalchemy

start=time.time()
ServerName = "DESKTOP-MRX\SQLEXPRESS"
Database = 'MYDATABASE'
params = '?driver=SQL+Server+Native+Client+11.0'
engine = create_engine('mssql+pyodbc://' + ServerName + '/'+ Database + params, encoding ='latin1' )
conn=engine.connect()

df=pd.DataFrame()
df['mixed']=np.arange(0,9)
df.iloc[0,0]='test'
df['numb']=3.0
df['text']='my string'
df.iloc[0,2]=np.nan
df.iloc[1,2]=999999999999999999999999999999999

df['text']=df['text'].astype(str).replace('nan',np.nan)

df.to_sql('test_df_mixed_types', engine, schema='dbo', if_exists='replace')
s5a0g9ez

s5a0g9ez1#

使用np.where肯定比替换(即

df['text'] = np.where(pd.isnull(df['text']),df['text'],df['text'].astype(str))

时间:

%%timeit
df['text'].astype(str).replace('nan',np.nan)
1000 loops, best of 3: 536 µs per loop

%%timeit
np.where(pd.isnull(df['text']),df['text'],df['text'].astype(str))
1000 loops, best of 3: 274 µs per loop

x = pd.concat([df['text']]*10000)
%%timeit
np.where(pd.isnull(x),x,x.astype(str))
10 loops, best of 3: 28.8 ms per loop

%%timeit
x.astype(str).replace('nan',np.nan)
10 loops, best of 3: 33.5 ms per loop
ztigrdn8

ztigrdn82#

若要将NaN保留为NaN并且仅将非NaN行转换为str,请使用布尔索引。

msk = df['text'].notna()
df.loc[msk, 'text'] = df.loc[msk, 'text'].astype(str)

或者使用mask()方法根据条件(值是否为非NaN)选择值,类似于np.where()

df['text'] = df['text'].mask(lambda x: x.notna(), df['text'].astype(str))

但是,如果您希望将NaN转换为空字符串(可能是为了稍后对字符串进行操作),则使用fillna()

df['text'] = df['text'].fillna('').astype(str)

相关问题