这种方法基于 gbrener 的答案。它遍历数据框以查找混合 dtype 列。对于每个这样的混合列,它首先用 pd.NA 替换所有 nan 值。然后安全地将其值转换为字符串。可以在原地使用,如 unmix_dtypes(df)。它在 Python 3.8 下的 Pandas 1 中进行了测试。
请注意,此答案使用
赋值表达式,仅适用于 Python 3.8 或更新版本。但是,它可以轻松修改为不使用它们。
from typing import Union
import pandas as pd
def _to_str(val: Union[type(pd.NA), float, int, str]) -> Union[type(pd.NA), str]:
"""Return a string representation of the given integer, rounded float, or otherwise a string.
`pd.NA` values are returned as is.
It can be useful to call `df[col].fillna(value=pd.NA, inplace=True)` before calling this function.
"""
if val is pd.NA:
return val
if isinstance(val, float) and (val % 1 == 0.0):
return str(int(val))
if isinstance(val, int):
return str(val)
assert isinstance(val, str)
return val
def unmix_dtypes(df: pd.DataFrame) -> None:
"""Convert mixed dtype columns in the given dataframe to strings.
Ref: https://dev59.com/LpDea4cB1Zd3GeqPbGiH#61826020/
"""
for col in df.columns:
if not (orig_dtype := pd.api.types.infer_dtype(df[col])).startswith("mixed"):
continue
df[col].fillna(value=pd.NA, inplace=True)
df[col] = df[col].apply(_to_str)
if (new_dtype := pd.api.types.infer_dtype(df[col])).startswith("mixed"):
raise TypeError(f"Unable to convert {col} to a non-mixed dtype. Its previous dtype was {orig_dtype} and new dtype is {new_dtype}.")
注意:不指定明确的数据类型的一个危险是,例如列["012", "0034", "4"]
可能被pd.read_csv
读取为整数列,从而不可挽回地丢失前导零。更糟糕的是,如果连接数据框,这种前导零的丢失可能会不一致地发生,导致列值如["012", "12", "34", "0034"]。
.0
的数字。它们是float
类型的。您是否想先将它们转换为int
类型? - TigerhawkT3low_memory=False
设置为read_csv()
的参数有所帮助。如果我不这样做,即使在csv文件中实际上没有小数点(只有整数值与其他字符串混合,但有许多(> 10k)行),浮点数(作为字符串)也会被读取。 - orange