如何使 pandas 在读取 CSV 文件时对 int64 列使用空值
How to make pandas to use nulls for int64 column when reading CSV file
我正在尝试读取导出为 CSV 的旧 DBase 文件,但有些列是空的。
首先,我在将整数列转换为浮点数时遇到了问题,但在这里遇到了@Nathan 的回答
问题解决了。
在我有正确的列类型之后 - 使用下面的代码:
def read_csv(file_name):
# todo set correct data types for the columns
inferred_types = {}
columns = pd.read_csv(file_name + '.csv', header=0, index_col=1, squeeze=True, keep_default_na=False, nrows=0).columns
for col in columns:
col_type = col.split(',')
try:
if len(col_type) < 2:
inferred_types[col] = str
elif col_type[1] == 'C':
inferred_types[col] = str
elif col_type[1] == 'N':
if 'EGN' in col: # special case
inferred_types[col] = str
else:
if col_type[3] == '0':
inferred_types[col] = np.int64
else:
inferred_types[col] = np.float64
else:
inferred_types[col] = str
except Exception as e:
print(f'{file_name} {col} -> {e}')
df = pd.read_csv(
file_name + '.csv', header=0, index_col=1, squeeze=True, keep_default_na=False, dtype=inferred_types
)
return df
当 pandas 命中列中的空单元格时,我得到了一个 ValueError。
请问我在这里遗漏了什么?
编辑:
以下是其中一个有问题的文件的前几行:
,"CODE_CURR,N,2,0","CURRENCIES,C,20","CUOZN,C,3","FOR_WHAT,N,5,0","CURS_DT,N,13,7","DATE_VAL,C,8","DATE_ACT,C,8","TIME_ACT,C,8","ID_NUMBER,C,2","SUBS_CODE,C,7","USER_CODE,C,7"
0,1,австралийски долари,AUD,,46.665,,,,,,
1,2,австрийски шилинги,ATS,,5.758,,,,,,
2,3,белгийски франкове,BEF,,1.969,,,,,,
问题是列“FOR_WHAT,N,5,0”(应该是整数)完全是空的,所以 ValueError:
ValueError: invalid literal for int() with base 10: ''
编辑2:
我将非常感谢任何解决方法!
数据集不是很大,所以性能不是问题。
您有两种方法可以在包含整数值的 Pandas 列中使用 NULL 值(在数据库意义上)。
仍然是官方方式:将列转换为 float64 并将 NaN 用于 NULL 值。
好处是 np.nan
支持在大多数数据库适配器中都很好,因此如果您在数据库中插入(或更新)所有 NaN 值,它们应该自动转换为 NULL 数据库值。缺点是 float64 不能准确地保存大于 2**48 的整数值(IEEE 754 尾数只有 48 位)。
实验方式:使用新的pd.Int64Dtype
这个新类型可以容纳任何 64 位整数值和一个特殊的 pd.NA
值。所以它提供了你想要的。这里的缺点是 documentation 明确地说:
IntegerArray is currently experimental. Its API or implementation may change without warning.
长话短说,它可能适用于您的用例(支持数据库适配器),如果 某事 在更高版本中发生变化,您可能必须调整您的代码.
我正在尝试读取导出为 CSV 的旧 DBase 文件,但有些列是空的。
首先,我在将整数列转换为浮点数时遇到了问题,但在这里遇到了@Nathan 的回答
def read_csv(file_name):
# todo set correct data types for the columns
inferred_types = {}
columns = pd.read_csv(file_name + '.csv', header=0, index_col=1, squeeze=True, keep_default_na=False, nrows=0).columns
for col in columns:
col_type = col.split(',')
try:
if len(col_type) < 2:
inferred_types[col] = str
elif col_type[1] == 'C':
inferred_types[col] = str
elif col_type[1] == 'N':
if 'EGN' in col: # special case
inferred_types[col] = str
else:
if col_type[3] == '0':
inferred_types[col] = np.int64
else:
inferred_types[col] = np.float64
else:
inferred_types[col] = str
except Exception as e:
print(f'{file_name} {col} -> {e}')
df = pd.read_csv(
file_name + '.csv', header=0, index_col=1, squeeze=True, keep_default_na=False, dtype=inferred_types
)
return df
当 pandas 命中列中的空单元格时,我得到了一个 ValueError。
请问我在这里遗漏了什么?
编辑: 以下是其中一个有问题的文件的前几行:
,"CODE_CURR,N,2,0","CURRENCIES,C,20","CUOZN,C,3","FOR_WHAT,N,5,0","CURS_DT,N,13,7","DATE_VAL,C,8","DATE_ACT,C,8","TIME_ACT,C,8","ID_NUMBER,C,2","SUBS_CODE,C,7","USER_CODE,C,7"
0,1,австралийски долари,AUD,,46.665,,,,,,
1,2,австрийски шилинги,ATS,,5.758,,,,,,
2,3,белгийски франкове,BEF,,1.969,,,,,,
问题是列“FOR_WHAT,N,5,0”(应该是整数)完全是空的,所以 ValueError:
ValueError: invalid literal for int() with base 10: ''
编辑2: 我将非常感谢任何解决方法! 数据集不是很大,所以性能不是问题。
您有两种方法可以在包含整数值的 Pandas 列中使用 NULL 值(在数据库意义上)。
仍然是官方方式:将列转换为 float64 并将 NaN 用于 NULL 值。
好处是
np.nan
支持在大多数数据库适配器中都很好,因此如果您在数据库中插入(或更新)所有 NaN 值,它们应该自动转换为 NULL 数据库值。缺点是 float64 不能准确地保存大于 2**48 的整数值(IEEE 754 尾数只有 48 位)。实验方式:使用新的
pd.Int64Dtype
这个新类型可以容纳任何 64 位整数值和一个特殊的
pd.NA
值。所以它提供了你想要的。这里的缺点是 documentation 明确地说:IntegerArray is currently experimental. Its API or implementation may change without warning.
长话短说,它可能适用于您的用例(支持数据库适配器),如果 某事 在更高版本中发生变化,您可能必须调整您的代码.