Pandas:读取带引号的值,逗号作为小数点分隔符,句点作为数字分组符号的csv
Pandas: Read csv with quoted values, comma as decimal separator, and period as digit grouping symbol
更新:最初发布问题时,我没有意识到 .
在某些条目中用作数字分组符号。但是,此信息对于解决问题至关重要。这是原始问题:
我目前正在尝试在 pandas 中导入一个格式不太完美的 csv 文件,因为包括数字在内的所有值都被引用了。格式如下所示:
Date;Type;Amount;Currency;Category;Person;Account;Counter Account;Group;Note
"19.02.17";"Expenses";"-36,37";"EUR";"Groceries";"";"Bank account";"";"";""
现在,我尝试使用以下命令导入它:
import pandas
dtypes = {"Type":"string", "Amount": "float"}
table = pandas.read_csv("data.csv", delimiter = ";", decimal = ",", parse_dates = ["Date"], dtype = dtypes, quoting = 3)
所以我基本上一直试图告诉 pandas 小数点分隔符是逗号,字段分隔符是分号,“金额”列应该解析为浮点数。但是,尝试解析文件时,我仍然收到错误消息:
ValueError: could not convert string to float: '689,15'"
我认为引号和逗号小数点分隔符的组合对于 pandas 来说有点太多了,尽管我认为我在技术上已经为它提供了它需要的所有信息。
该文件是从第三方程序导出的,所以很遗憾,我对格式没有影响。 有谁知道如何让 pandas 吞下这个?
奖励问题:如果我在没有提供明确数据类型的情况下读取此文件,我不会像我预期的那样得到任何类型为“string”的列,而是使用“object”。这是为什么?
更新:虽然这个答案仍然有效,但有一个更简单的解决方案。我最初没有意识到某些条目使用 .
作为数字分组符号,因此造成混淆。
好的,我找到了一种使用 converters
参数传递执行转换的 lambda 的方法。到目前为止我找不到更简单的解决方案。
toFloat = lambda x: float(x.replace(".", "").replace(",", "."))
table = pandas.read_csv("data.csv", delimiter = ";", decimal = ",", parse_dates = ["Date"], converters = {"Amount": toFloat})
lambda toFloat
接受一个字符串,删除所有出现的 .
字符(用作数字分组符号),用 .
替换所有出现的 ,
然后将生成的字符串转换为浮点数。然后,此 lambda 作为“金额”列的转换器传递给 read_csv
函数。可能现在 decimal
参数也是可以消耗的。
我暂时保留这个问题,看看是否有人能提出更简单的解决方案。
那个呢?
import pandas
table = pandas.read_csv("data.csv", sep=";", decimal=",")
print(table["Amount"][0]) # -36.37
print(type(table["Amount"][0])) # <class 'numpy.float64'>
print(table["Amount"][0] + 36.37) # 0.0
Pandas自动检测一个数字并将其转换为numpy.float64
.
编辑:
正如@bweber 所发现的,data.csv
中的某些值包含超过 3 个数字,并使用了数字分组符号 '.
'。为了将字符串转换为整数,必须将使用的符号传递给 read_csv() 方法:
table = pandas.read_csv("data.csv", sep=";", decimal=",", thousands='.')
更新:最初发布问题时,我没有意识到 .
在某些条目中用作数字分组符号。但是,此信息对于解决问题至关重要。这是原始问题:
我目前正在尝试在 pandas 中导入一个格式不太完美的 csv 文件,因为包括数字在内的所有值都被引用了。格式如下所示:
Date;Type;Amount;Currency;Category;Person;Account;Counter Account;Group;Note
"19.02.17";"Expenses";"-36,37";"EUR";"Groceries";"";"Bank account";"";"";""
现在,我尝试使用以下命令导入它:
import pandas
dtypes = {"Type":"string", "Amount": "float"}
table = pandas.read_csv("data.csv", delimiter = ";", decimal = ",", parse_dates = ["Date"], dtype = dtypes, quoting = 3)
所以我基本上一直试图告诉 pandas 小数点分隔符是逗号,字段分隔符是分号,“金额”列应该解析为浮点数。但是,尝试解析文件时,我仍然收到错误消息:
ValueError: could not convert string to float: '689,15'"
我认为引号和逗号小数点分隔符的组合对于 pandas 来说有点太多了,尽管我认为我在技术上已经为它提供了它需要的所有信息。
该文件是从第三方程序导出的,所以很遗憾,我对格式没有影响。 有谁知道如何让 pandas 吞下这个?
奖励问题:如果我在没有提供明确数据类型的情况下读取此文件,我不会像我预期的那样得到任何类型为“string”的列,而是使用“object”。这是为什么?
更新:虽然这个答案仍然有效,但有一个更简单的解决方案。我最初没有意识到某些条目使用 .
作为数字分组符号,因此造成混淆。
好的,我找到了一种使用 converters
参数传递执行转换的 lambda 的方法。到目前为止我找不到更简单的解决方案。
toFloat = lambda x: float(x.replace(".", "").replace(",", "."))
table = pandas.read_csv("data.csv", delimiter = ";", decimal = ",", parse_dates = ["Date"], converters = {"Amount": toFloat})
lambda toFloat
接受一个字符串,删除所有出现的 .
字符(用作数字分组符号),用 .
替换所有出现的 ,
然后将生成的字符串转换为浮点数。然后,此 lambda 作为“金额”列的转换器传递给 read_csv
函数。可能现在 decimal
参数也是可以消耗的。
我暂时保留这个问题,看看是否有人能提出更简单的解决方案。
那个呢?
import pandas
table = pandas.read_csv("data.csv", sep=";", decimal=",")
print(table["Amount"][0]) # -36.37
print(type(table["Amount"][0])) # <class 'numpy.float64'>
print(table["Amount"][0] + 36.37) # 0.0
Pandas自动检测一个数字并将其转换为numpy.float64
.
编辑:
正如@bweber 所发现的,data.csv
中的某些值包含超过 3 个数字,并使用了数字分组符号 '.
'。为了将字符串转换为整数,必须将使用的符号传递给 read_csv() 方法:
table = pandas.read_csv("data.csv", sep=";", decimal=",", thousands='.')