【问题标题】:Convert decimal mark when reading numbers as input读取数字作为输入时转换小数点
【发布时间】:2011-10-29 16:52:15
【问题描述】:

我有一个 CSV 文件,其中包含我想读入 Python 的数据读取。我得到包含"2,5" 之类的字符串的列表。现在做float("2,5") 不起作用,因为它有错误的小数点。

如何将其作为2.5 读入Python?

【问题讨论】:

标签: python locale decimal-point


【解决方案1】:

如果将点用作千位分隔符,则要交换逗号和点,您可以使用第三个符号作为临时占位符,如下所示:

value.replace('.', '#').replace(',', '.').replace('#', ',')

但是看到你想从字符串转换为浮点数,你可以删除任何点,然后用点替换任何逗号

float(value.replace('.', '').replace(',', '.'))

IMO 这是最易读的解决方案

【讨论】:

    【解决方案2】:

    首先您必须确保用于提供号码的区域设置。不这样做肯定会出现随机问题。

    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
    

    【讨论】:

    • 作为警告,让我在这里引用文档:``` 在某些库例程中调用 setlocale() 通常是个坏主意,因为它会影响整个程序。保存和恢复它几乎一样糟糕:它很昂贵并且会影响在设置恢复之前碰巧运行的其他线程。 ```
    【解决方案3】:

    float("2,5".replace(',', '.')) 在大多数情况下都可以

    如果value是一个很大的数字,而.已经用了几千,你可以:

    将所有逗号替换为点:value.replace(",", ".")

    删除除最后一点之外的所有内容:value.replace(".", "", value.count(".") -1)

    【讨论】:

    • 只是好奇,这是真正的解决方案吗?对我来说看起来很糟糕。
    • 这不是一个全球性的标准。例如,在俄罗斯,逗号是标准的,点并没有被广泛使用。所以,我相信,这个问题的正确解决方案是以某种方式了解本文档的作者语言环境。另一个问题是 - 既然我们在谈论 CSV,他们是如何设法用逗号保存浮点数的? :-)。我相信 3,14 是 2 个整数而不是浮点数。
    • @lok​​i2302 csv 文件中以逗号作为十进制分隔符 is to use ; as field delimiter 的国家/地区的标准 csv 格式。
    • 标准分隔符是逗号。每个人都知道,除了美国人和英国人:D
    • @Jean-FrançoisCorbett 我想我还不够清楚。我的观点很简单,分隔符取决于您使用的语言,主要是数字在历史上的表示方式。基于英语的语言和基于拉丁语的语言使用不兼容的系统,这就是为什么英国和前殖民地出现在您的列表中。问候!
    【解决方案4】:

    Pandas 支持这个开箱即用:

    df = pd.read_csv(r'data.csv', decimal=',')
    

    http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html

    【讨论】:

    • 是否有一些现成的命令可以在 pandas 中用点小数点替换逗号小数点(无需用一些正则表达式进行蛮力替换)?
    • 没有找到。但是通过 apply 或 applymap 替换它有什么问题?
    【解决方案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")
    

    使用此方法前请阅读this 部分。

    【讨论】:

    【解决方案6】:

    尝试用小数点替换所有小数点:

    floatAsStr = "2,5"
    floatAsStr = floatAsStr.replace(",", ".");
    myFloat = float(floatAsStr)
    

    当然,函数replace 可以处理任何子字符串,因为python 现在可以区分字符和字符串。

    【讨论】:

    • str 是一个糟糕的变量名。
    • 你是对的,我只是从一些教程页面复制代码并添加了最后一行......
    • floatAsStr 也好不到哪里去。 :-P
    【解决方案7】:

    使用正则表达式会更可靠

    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 )
    

    如果您想处理更复杂的情况(例如小数点前没有数字的数字),我为检测以下线程中所有类型的数字而精心设计的正则表达式可能会让您感兴趣:

    stackoverflow.com/questions/5917082/regular-expression-to-match-numbers-with-or-without-commas-and-decimals-in-text/5929469

    【讨论】:

    • 如何在 pandas 数据帧(不是字符串)上做到这一点?
    猜你喜欢
    • 2021-11-06
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2015-03-12
    相关资源
    最近更新 更多