Преобразовать десятичную метку
У меня есть файл CSV с чтением данных, который я хочу прочитать в Python. Я получаю списки, которые содержат строки, такие как "2,5"
, Сейчас занимаюсь float("2,5")
не работает, потому что имеет неправильный десятичный знак.
Как мне прочитать это в Python как 2.5
?
8 ответов
float("2,5".replace(',', '.'))
будет делать в большинстве случаев
Если value
большое количество и .
был использован для тысяч, вы можете:
Замените все запятые для точек: value.replace(",", ".")
Удалить все, кроме последнего пункта: value.replace(".", "", value.count(".") -1)
Вы можете сделать это с учетом местных условий:
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")
Прочтите этот раздел, прежде чем использовать этот метод.
Панды поддерживают это из коробки:
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 )
Если вы хотите рассматривать более сложные случаи (числа без цифр перед десятичной отметкой для примера), то для вас может представлять интерес регулярное выражение, разработанное для обнаружения всех типов чисел в следующей цепочке:
Попробуйте заменить все запятые на десятичные точки:
floatAsStr = "2,5"
floatAsStr = floatAsStr.replace(",", ".");
myFloat = float(floatAsStr)
Функция replace
Конечно, работа с любой подстрокой, так как python теперь различает char и string.
Сначала вы должны убедиться, какая локаль использовалась для предоставления номера. Несоблюдение этого правила может привести к случайным проблемам.
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
если точки используются как разделители тысяч, чтобы поменять местами запятые и точки, вы можете использовать третий символ в качестве временного заполнителя, например:
value.replace('.', '#').replace(',', '.').replace('#', ',')
но, видя, что вы хотите преобразовать в float из строки, вы можете просто удалить любые точки, а затем заменить любые запятые точками
float(value.replace('.', '').replace(',', '.'))
ИМО это наиболее читаемое решение
У меня есть приложение (не под моим контролем), в котором входящее денежное значение может быть в любом из двух форматов, по крайней мере, пока мы убеждаем клиента изменить это. При указании одного разделителя возникает двусмысленность: 1039 может означать 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)