Pandas数据框将列解释为浮点数而不是字符串

12
我想将一个csv文件导入Pandas数据框中。其中有一个只包含数字的ID列,但并不是每一行都有ID。

我想将一个csv文件导入Pandas数据框中。其中有一个只包含数字的ID列,但并不是每一行都有ID。

   ID      xyz
0  12345     4.56
1           45.60
2  54231   987.00

我想将这一列作为字符串来读取,但是即使我使用下面的代码指定了它的数据类型:

df=pd.read_csv(filename,dtype={'ID': str})

我还是得到了以下结果:

   ID         xyz
0  '12345.0'    4.56
1   NaN        45.60
2  '54231.0'  987.00

是否有一种简单的方法可以获取ID作为字符串而不是十进制,例如'12345',而无需在导入表格后编辑字符串?


数值列中是否可能存在空值? - jezrael
如果您的关注点是输出格式,那么请在导出数据时进行修复(例如 to_csvto_string),而不是通过更改底层数据(看起来很好)为笨拙的类型来解决问题。 - jpp
我认为你可以升级你的pandas版本,这样一切都会很好。 - jezrael
我的底层数据是一个 CSV 文件,其中包含一个 ID,该 ID 不应被视为数字,而应视为标识符。字符串似乎是最好的表示方法。 - Georg B
3个回答

9
一个解决方案可以是这样的,但在您导入df之后:
df = pd.read_csv(filename)
df['ID'] = df['ID'].astype(int).astype(str)

或者因为有NaN与:

df['ID'] = df['ID'].apply(lambda x: x if pd.isnull(x) else str(int(x)))

1
无法工作,因为我有空单元格,而NaN值无法转换为int。 - Georg B
1
那个有效,谢谢。我尝试了类似的东西,但你的效果更好。 - Georg B
1
这让我在查看其他不起作用的答案半个小时后得救了。谢谢! - Nazanin Zinouri
如果我们有一个值为“00212”的单元格,我们该怎么做?@joe - rahnama7m

1
如果缺失值不在数值列中,可能的解决方案是使用参数keep_default_na=False,这样可以避免将空值转换为字符串,但它不会将所有数据都转换为NaN,也不一定总是在第一列中转换。请参阅文档
import pandas as pd

temp=u"""ID;xyz
0;12345;4.56
1;;45.60
2;54231;987.00"""
#after testing replace 'pd.compat.StringIO(temp)' to 'filename.csv'
df = pd.read_csv(pd.compat.StringIO(temp), sep=";", dtype={'ID': str}, keep_default_na=False)
    print (df)
      ID     xyz
0  12345    4.56
1          45.60
2  54231  987.00

编辑:

对于我来说,在pandas 0.23.4中,你的解决方案完美地运行,这意味着在较低版本的pandas中存在错误:

import pandas as pd

temp=u"""ID;xyz
0;12345;4.56
1;;45.60
2;54231;987.00"""
#after testing replace 'pd.compat.StringIO(temp)' to 'filename.csv'
df = pd.read_csv(pd.compat.StringIO(temp), sep=";", dtype={'ID': str})
print (df)
      ID     xyz
0  12345    4.56
1    NaN   45.60
2  54231  987.00

它对你的示例可行,但对我的CSV文件无效。与先前的结果唯一的区别是“NaN”变成了空字符串。 我真的很困惑,我再次检查了我的文件,但其中绝对没有浮点数。 - Georg B
@GeorgB - 如果ID列预期的输出不是空字符串,那么它应该是什么? - jezrael
只要我有一个简单的方法来过滤掉空列,那么空列并不重要。我只需要非空ID作为字符串,末尾没有“.0”。用户Joe给出了一个有效的答案,所以我可以继续。只是感觉在读取文件时有一种方法可以做到这一点,而不是之后再处理。 - Georg B
@GeorgB - df['ID'] = df['ID'].apply(lambda x: x if pd.isnull(x) else str(int(x))) 这是你的解决方案吗? - jezrael
1
谢谢您提供的解决方案!您修改后的代码段 dtype={'ID': str} 解决了我的问题!我一直在失去需要保留的前导零,所以我需要使用正确的模式读取它。非常感谢您的建议! - yeamusic21
显示剩余2条评论

0

在写入csv时指定浮点格式

由于您导出数据时的根本问题是输出格式,因此不需要进行任何操作。只需使用以下代码:

df.to_csv('file.csv', float_format='%.0f')

如果您只想使特定列具有此格式,可以使用{{link1:to_string}}:

def format_int(x):
    return f'{x:.0f}' if x==x else ''

with open('file.csv', 'w') as fout:
    fout.write(df.to_string(formatters={'ID': format_int}))

保持数字数据的数字性质

有一列ID,它们只由数字组成

如果您的列仅包含数字,请不要将其转换为字符串! 您想要转换为字符串似乎是一个XY问题。 数字标识符应保持为数字。

浮点数NaN会导致上转型

您的问题是NaN值无法与数字系列中的整数共存。 由于NaNfloat,因此Pandas强制进行上转型。 这是自然的,因为object dtype替代方案效率低下且不推荐使用。

如果可行,您可以使用一个哨兵值,例如-1来表示空值:

df['ID'] = pd.to_numeric(df['ID'], errors='coerce').fillna(-1).astype(int)

print(df)

      ID     xyz
0  12345    4.56
1     -1   45.60
2  54231  987.00

如果您的列只包含数字,请不要将其转换为字符串!- 如果操作需要将数字转换为字符串,为什么不呢?这有什么问题吗? - jezrael
@jezrael,XY问题:“XY问题是指询问你尝试解决的方案而非你实际面临的问题。” - jpp
1
好的,请在问题下面的评论中添加有关XY问题的评论,但如果需要将数字列转换为字符串,那也绝对没有错。 - jezrael
1
我需要它们作为字符串,或者至少是可以转换为字符串的整数。 如果我找不到其他选项,我会尝试你的方法,但每次保存文件时都必须删除-1。 - Georg B
1
我不投票,因为“不要转化为字符串!”是错误的陈述。 - jezrael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接