我正在使用Pandas数据框。我有一个来自CSV的列,它是整数与null混合在一起。
我正尝试将其转换并以尽可能通用的方式将其插入Spanner(以便将来的工作可以使用相同的代码),这降低了我使用前哨变量的能力。但是,DF无法处理纯int列中的NaN
,因此您必须使用Int64
。当我尝试将其插入Spanner时,我得到一个错误,它不是int64
类型,而纯Python int
确实可以工作。在插入过程中,有没有一种自动的方法可以将Int64
的熊猫值转换为int
的值?再次,由于空值,在插入之前转换列不起作用。有其他解决方法吗?
尝试从系列中进行转换是这样的:
>>>s2=pd.Series([3.0,5.0])
>>>s2
0 3.0
1 5.0
dtype: float64
>>>s1=pd.Series([3.0,None])
>>>s1
0 3.0
1 NaN
dtype: float64
>>>df = pd.DataFrame(data=[s1,s2], dtype=np.int64)
>>>df
0 1
0 3 NaN
1 3 5.0
>>>df = pd.DataFrame(data={"nullable": s1, "nonnullable": s2}, dtype=np.int64)
最后一条命令产生错误ValueError: Cannot convert non-finite values (NA or inf) to integer
答案 0 :(得分:0)
我无法重现您的问题,但似乎每个人都按预期工作
是否有可能要向其中写入空值的不可为空的列?
from google.cloud import spanner
client = spanner.Client()
database = client.instance('testinstance').database('testdatabase')
table_name='inttable'
query = f'''
SELECT
t.column_name,
t.spanner_type,
t.is_nullable
FROM
information_schema.columns AS t
WHERE
t.table_name = '{table_name}'
'''
with database.snapshot() as snapshot:
print(list(snapshot.execute_sql(query)))
# [['nonnullable', 'INT64', 'NO'], ['nullable', 'INT64', 'YES']]
from google.cloud import spanner
import numpy as np
import pandas as pd
client = spanner.Client()
instance = client.instance('testinstance')
database = instance.database('testdatabase')
def insert(df):
with database.batch() as batch:
batch.insert(
table='inttable',
columns=(
'nonnullable', 'nullable'),
values=df.values.tolist()
)
print("Succeeds in inserting int rows.")
d = {'nonnullable': [1, 2], 'nullable': [3, 4]}
df = pd.DataFrame(data=d, dtype=np.int64)
insert(df)
print("Succeeds in inserting rows with None in nullable columns.")
d = {'nonnullable': [3, 4], 'nullable': [None, 6]}
df = pd.DataFrame(data=d, dtype=np.int64)
insert(df)
print("Fails (as expected) attempting to insert row with None in a nonnullable column fails as expected")
d = {'nonnullable': [5, None], 'nullable': [6, 0]}
df = pd.DataFrame(data=d, dtype=np.int64)
insert(df)
# Fails with "google.api_core.exceptions.FailedPrecondition: 400 nonnullable must not be NULL in table inttable."
答案 1 :(得分:0)
我的解决方案是将其保留为NaN
(原来是NaN == 'nan'
)。然后,最后,当我插入Spanner DB时,我在DF中用NaN
替换了所有None
。我使用了另一个SO答案:df.replace({pd.np.nan: None})
中的代码。 Spanner将NaN
视为'nan'
字符串,并拒绝将其插入Int64列。 None
被视为NULL
,可以毫无问题地插入Spanner。