我有一个包含数据读取的 CSV 文件,我想将其读入 Python。我得到包含
"2,5"
等字符串的列表。现在做 float("2,5")
不起作用,因为它的小数点错误。
如何将其读入 Python 中作为
2.5
?
您可以通过区域设置感知的方式进行操作:
import locale
# Set to users preferred locale:
locale.setlocale(locale.LC_ALL, '')
# Or a specific locale:
locale.setlocale(locale.LC_NUMERIC, "en_DK.UTF-8")
print locale.atof("3,14")
使用此方法之前,请阅读此部分。
float("2,5".replace(',', '.'))
在大多数情况下都可以
如果
value
是一个很大的数字并且.
已被使用了数千次,您可以:
替换点的所有逗号:
value.replace(",", ".")
删除除最后一点之外的所有内容:
value.replace(".", "", value.count(".") -1)
Pandas 支持开箱即用:
df = pd.read_csv(r'data.csv', decimal=',')
参见 http://pandas.pydata.org/pandas-docs/stable/ generated/pandas.read_csv.html
使用正则表达式会更可靠
import re
decmark_reg = re.compile('(?<=\d),(?=\d)')
ss = 'abc , 2,5 def ,5,88 or (2,5, 8,12, 8945,3 )'
print ss
print decmark_reg.sub('.',ss)
结果
abc , 2,5 def ,5,88 or (2,5, 8,12, 8945,3 )
abc , 2.5 def ,5.88 or (2.5, 8.12, 8945.3 )
如果您想处理更复杂的情况(例如,小数点前没有数字的数字),您可能会对我制作的用于检测以下线程中所有类型数字的正则表达式感兴趣:
首先您必须确保使用什么区域设置来提供号码。如果不做到这一点,肯定会出现随机问题。
import locale
loc = locale.getlocale() # get and save current locale
# use locale that provided the number;
# example if German locale was used:
locale.setlocale(locale.LC_ALL, 'de_DE')
pythonnumber = locale.atof(value)
locale.setlocale(locale.LC_ALL, loc) # restore saved locale
尝试将所有小数逗号替换为小数点:
float_as_str = "2,5"
float_as_str = float_as_str.replace(",", ".");
some_float = float(float_as_str)
函数
replace
当然可以处理任何子字符串,因为 python 现在可以区分 char 和 string。
如果使用点作为千位分隔符,要交换逗号和点,您可以使用第三个符号作为临时占位符,如下所示:
value.replace('.', '#').replace(',', '.').replace('#', ',')
但是当你想从字符串转换为浮点数时,你可以删除任何点,然后用点替换任何逗号
float(value.replace('.', '').replace(',', '.'))
IMO这是最具可读性的解决方案
我有一个应用程序(不受我控制),其中传入的货币价值可以采用两种格式中的任何一种,至少在我们说服客户更改此设置时是这样。提供单个分隔符时存在歧义:1,039 可能意味着 1.036 或 1036(千和...),但实际上,由于表示的是金钱,因此分隔符后面超过 2 个字符被假定为非小数。
下面是这段代码:
def tolerant_monetary_float (x, max_decimals = 2):
num_dot = x.count ('.')
num_com = x.count (',')
if not num_dot:
# no dot
if not num_com:
# no dot, no comma
return float (x)
if num_com > 1:
# more than one comma
return float (x.replace (',', ''))
# 1 comma: its ambiguous: 1,000 can mean 1000 or 1.0
if len (x) - x.find (',') -1 <= max_decimals:
# assume the comma is decimal separator
return float (x.replace (',', '.'))
# assume comma is thousand separator
return float (x.replace (',', ''))
if not num_com:
# no comma
if not num_dot:
# no dot, no comma
return float (x)
if num_dot > 1:
# more than one dot
return float (x.replace ('.', ''))
# 1 dot: its ambiguous: 1.000 can mean 1000 or 1.0
if len (x) - x.find ('.') -1 <= max_decimals:
# assume the dot is decimal separator
return float (x)
# assume dot is thousand separator
return float (x.replace ('.', ''))
# mix of dots and commas
if num_dot > 1 and num_com > 1:
return ValueError (f'decimal number cannot have a mix of "," and ".": {x}')
ix_dot = x.find ('.')
ix_com = x.find (',')
if ix_dot < ix_com:
# dot is before comma: 1.000,35
return float (x.replace ('.', '').replace (',', '.'))
# comma is before dot: 1,000.35
return float (x.replace (',', ''))
if __name__ == "__main__":
assert (tolerant_monetary_float ('1') == 1.0)
assert (tolerant_monetary_float ('1.2345') == 12345.0)
assert (tolerant_monetary_float ('1.234') == 1234.0)
assert (tolerant_monetary_float ('1.23') == 1.23)
assert (tolerant_monetary_float ('1.2') == 1.2)
assert (tolerant_monetary_float ('1,2345') == 12345.0)
assert (tolerant_monetary_float ('1,234') == 1234.0)
assert (tolerant_monetary_float ('1,23') == 1.23)
assert (tolerant_monetary_float ('1,2') == 1.2)
assert (tolerant_monetary_float ('1234,5') == 1234.5)
assert (tolerant_monetary_float ('1.234,5') == 1234.5)
assert (tolerant_monetary_float ('1,234.5') == 1234.5)
assert (tolerant_monetary_float ('1,234,567.85') == 1234567.85)
assert (tolerant_monetary_float ('1.234.567,85') == 1234567.85)