печать чисел с плавающей запятой менее 1 в python [дубликат]

dplyr с 0,4 реализовал все те объединения, в том числе external_join, но стоит отметить, что для первых нескольких релизов он использовал не для того, чтобы предлагать внешний_join, и в результате было много действительно плохой взломанный обходной код пользователя, плавающий вокруг (вы все еще можете найти это в ответах SO и Kaggle с того периода).

Основные моменты выделения :

v0.5 (6/2016)

  • Обработка для типа POSIXct, часовых поясов, дубликатов, разных уровней факторов. Более эффективные ошибки и предупреждения.
  • Новый аргумент суффикса для управления тем, какие суффиксные имена дублированных переменных получают (# 1296)

v0.4.0 (1/2015)

  • Внедрить правое соединение и внешнее соединение (# 96)
  • Мутирующие объединения, которые добавляют новые переменные в одну таблицу из совпадающих строк в другой. Фильтрация соединений, которые фильтруют наблюдения из одной таблицы на основе того, соответствуют ли они наблюдению в другой таблице.

v0.3 (10/2014)

  • Теперь можно оставить left_join разными переменными в каждой таблице: df1%>% left_join (df2, c ("var1" = "var2"))

v0.2 (5/2014)

  • * _ join () больше не переупорядочивает имена колонок (# 324)

v0.1.3 (4/2014)

Обходные решения для комментариев хайли в этой проблеме:

  • right_join (x, y) совпадает с left_join (y, x) в терминов строк, только столбцы будут разными порядками.
  • external_join - это в основном union (left_join (x, y), right_join (x, y)) - то есть сохранить все строки в обоих кадрах данных.

29
задан Henk Langeveld 12 May 2014 в 13:27
поделиться

11 ответов

Вы можете использовать следующий класс MyFloat вместо встроенного класса float.

def _remove_leading_zero(value, string):
    if 1 > value > -1:
        string = string.replace('0', '', 1)
    return string


class MyFloat(float):
    def __str__(self):
        string = super().__str__()
        return _remove_leading_zero(self, string)

    def __format__(self, format_string):
        string = super().__format__(format_string)
        return _remove_leading_zero(self, string)

С помощью этого класса вам придется использовать функцию str.format вместо оператора модуля ( %) для форматирования. Ниже приведены некоторые примеры:

>>> print(MyFloat(.4444))
.4444

>>> print(MyFloat(-.4444))
-.4444

>>> print('some text {:.3f} some more text',format(MyFloat(.4444)))
some text .444 some more text

>>> print('some text {:+.3f} some more text',format(MyFloat(.4444)))
some text +.444 some more text

Если вы также хотите заставить оператор модуля (%) класса str вести себя одинаково, тогда вам придется переопределить __mod__ метод класса str путем подкласса класса. Но это будет не так просто, как переопределить метод __format__ класса float, так как в этом случае отформатированное число с плавающей точкой может присутствовать в любой позиции в результирующей строке.

[Примечание: Все приведенные выше коды написаны на Python3. Вам также придется переопределить __unicode__ в Python2, а также изменить вызовы super.]

PS: Вы также можете переопределить метод __repr__, аналогичный __str__, если вы также хотите изменить официальное строковое представление в MyFloat.




Изменить: на самом деле вы можете добавить новый синтаксис для форматирования sting с помощью __format__ метод. Таким образом, если вы хотите сохранить оба поведения, то есть показывать ведущий нуль, когда это необходимо, и не показывать начальный ноль, когда это не нужно. Вы можете создать класс MyFloat следующим образом:

class MyFloat(float):
    def __format__(self, format_string):
        if format_string.endswith('z'):  # 'fz' is format sting for floats without leading the zero
            format_string = format_string[:-1]
            remove_leading_zero = True
        else:
            remove_leading_zero = False

        string = super(MyFloat, self).__format__(format_string)
        return _remove_leading_zero(self, string) if remove_leading_zero else string
        # `_remove_leading_zero` function is same as in the first example

И использовать этот класс следующим образом:

>>> print('some text {:.3f} some more text',format(MyFloat(.4444)))
some text 0.444 some more text
>>> print('some text {:.3fz} some more text',format(MyFloat(.4444)))
some text .444 some more text


>>> print('some text {:+.3f} some more text',format(MyFloat(.4444)))
some text +0.444 some more text
>>> print('some text {:+.3fz} some more text',format(MyFloat(.4444)))
some text +.444 some more text


>>> print('some text {:.3f} some more text',format(MyFloat(-.4444)))
some text -0.444 some more text
>>> print('some text {:.3fz} some more text',format(MyFloat(-.4444)))
some text -.444 some more text

Обратите внимание, что использование 'fz' вместо 'f' удаляет начальный нуль.

Кроме того, приведенный выше код работает как в Python2, так и в Python3.

4
ответ дан Debanshu Kundu 21 August 2018 в 20:31
поделиться
  • 1
    Действительно ли ваш remove_leading_zeros remove_all_zeros. Кажется неуклюжим и неправильным. – hobs 25 February 2016 в 01:22
  • 2
    @hobs, пожалуйста, проверьте код, прежде чем указывать какие-либо вопросы, он работает, как ожидалось. string.replace('0', '', 1) удалит только первый ноль, а условие if 1 > value > -1 будет убедиться, что оно применяется только тогда, когда строка находится в форме 0.<some digits>. – Debanshu Kundu 25 February 2016 в 11:28
  • 3
    Вот мой ( несправедливый / нереалистичный ) тестовый пример, который вызвал неправильный ответ: '.402'.replace('0', '', 1) - & gt; .42. Ваш код будет работать для всех строк, созданных __str__ на float s, как определено в настоящий момент, но ваш код является хрупким (неуклюжим). Это не идемпотент. И это невозможно для будущего. lstrip намного более кратким и надежным (идемпотентным и перспективным). Ваша операция replace не может применяться более одного раза. И если ваш конкретный тип номера не ограничивал способ создания python встроенных поплавков, хорошо ... – hobs 26 February 2016 в 04:32

Используйте .lstrip(), после использования форматирования строки для преобразования в строку:

>>> k = .1827412
>>> print ("%.4f"%(k)).lstrip('0')
.1827
>>> 

.lstrip() можно использовать для удаления любого из ведущих символов строки:

>>> k = 'bhello'
>>> print k.lstrip('b')
hello
>>> print k.lstrip('bhel')
o
>>> print k.lstrip('bel')
hello
>>> 

Из документов :

string.lstrip (s [, chars])

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; ; & nbsp; & nbsp; & nbsp; Возвращает копию строки с удаленными ведущими символами

3
ответ дан A.J. Uppal 21 August 2018 в 20:31
поделиться

Я бы лучше читал и прост, чем что-либо еще: Давайте обрабатывать знак и цифры независимо. И немного в строке, если утверждение никогда никого не повредит.

k = -.1337
"".join( ["-" if k < 0 else "", ("%.4f" % abs(k)).lstrip('0')] )
4
ответ дан John Haberstroh 21 August 2018 в 20:31
поделиться
  • 1
    Короче, если вы объединяете +, а не используете join. «Конечно, вам понадобится скобка вокруг логики знака. – jrennie 15 May 2014 в 09:11
  • 2
    Я изучил использование & quot; + & quot; для конкатенации, потому что я слышал, что это не очень питонов. Оказывается, что использование «.join () вместо + примерно на два порядка быстрее, и оно также лучше подходит для стиля python. Тем не менее, + полностью эквивалентен и, вероятно, легче придумать практически для любого случая использования. – John Haberstroh 19 May 2014 в 18:26

Насколько мне нравятся милые трюки регулярных выражений, я думаю, что простая функция - это лучший способ сделать это:

def formatFloat(fmt, val):
  ret = fmt % val
  if ret.startswith("0."):
    return ret[1:]
  if ret.startswith("-0."):
    return "-" + ret[2:]
  return ret

>>> formatFloat("%.4f", .2)
'.2000'
>>> formatFloat("%.4f", -.2)
'-.2000'
>>> formatFloat("%.4f", -100.2)
'-100.2000'
>>> formatFloat("%.4f", 100.2)
'100.2000'

Это имеет смысл быть понятным, частично потому, что startswith это простое совпадение строк, а не регулярное выражение.

7
ответ дан jrennie 21 August 2018 в 20:31
поделиться

Поскольку мы рассматриваем только> -1 для & lt; 1, тогда будет работать следующее редактирование.

import re
re.sub(r"0+\.", ".", %0.4f" % k)

Это будет поддерживать знак, только удаляя цифру слева от десятичной.

2
ответ дан NanoBennett 21 August 2018 в 20:31
поделиться
  • 1
    OP только хочет обрезать цифры слева от десятичной точки, когда число меньше 1 и больше -1, например 0,1 - & gt; .1000, но 1,0 - & gt; 1,0000 – nettux443 14 May 2014 в 01:11
  • 2
    Я обновился, чтобы больше соответствовать OP @ nettux443. Спасибо что подметил это. – NanoBennett 14 May 2014 в 17:16
import re
re.sub("^(\-?)0\.", r'\1.', "%.4f" % k)

Это короткий, простой и я не могу найти сценарий, для которого он не работает.

Примеры:

>>> import re
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 0)
'.0000'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 0.1337)
'.1337'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 1.337)
'1.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -0)
'.0000'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -0.1337)
'-.1337'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -1.337)
'-1.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 10.337)
'10.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -10.337)
'-10.3370'

Редактировать: Если вы рассматривают только числа> -10 и & lt; 10 Будет работать следующее:

("%.4f", k).replace('0.', '.')
3
ответ дан nettux443 21 August 2018 в 20:31
поделиться
  • 1
    Что относительно k=10.2 – Jacob Krall 14 May 2014 в 00:52
  • 2
    @JacobKrall блин, сэр! отредактирован для использования re.sub и теперь выполняется сопоставление скобок – nettux443 14 May 2014 в 01:07

Вот еще один способ:

>>> ("%.4f" % k).lstrip('0')
'.1337'

Он немного более общий, чем [1:], поскольку он также работает с числами> = 1.

Ни один из методов не корректно обрабатывает отрицательные номера, однако. В этом отношении лучше:

>>> re.sub('0(?=[.])', '', ("%0.4f" % -k))
'-.1337'

Не особенно изящно, но сейчас я не могу придумать лучшего метода.

26
ответ дан NPE 21 August 2018 в 20:31
поделиться
  • 1
    Я уверен, что есть другой способ, но я думаю, это работает. – Paul Seeb 26 April 2012 в 17:51
  • 2
    Регулярное выражение здесь не будет корректно работать с числами с абсолютным значением, большим десяти, которые имеют нуль в одном месте. Например, 100.1337 становится 10.1337. – musicinmybrain 12 May 2014 в 14:42
  • 3
    Я отредактировал регулярное выражение для работы со всеми входами реального числа. Ожидание экспертной оценки. (re.sub(r'^(-?)0(?=\.)', r'\1', ...)) – musicinmybrain 12 May 2014 в 14:47
  • 4
    @musicinmybrain Вы должны написать свой собственный ответ с этим регулярным выражением – Rob Watts 13 May 2014 в 20:52
  • 5
    @musicinmybrain Редактирование ответа другого человека - это очистка, когда что-то может быть сказано лучше, а не для коренного изменения ответа. Я согласен с Роба Уотсом, что вы должны создать свой собственный ответ. – jrennie 15 May 2014 в 09:06

Один жизнеспособный вариант, который работает без регулярного выражения и с отрицательными значениями больше 10

k = -.1337
("%.4f" % k).replace("-0","-").lstrip("0")
5
ответ дан Paul Seeb 21 August 2018 в 20:31
поделиться
  • 1
    . является метасимволом регулярного выражения. Вы понимаете, что произойдет, если k - -100.1337? – devnull 13 May 2014 в 20:17
  • 2
    @devnull Я принял ответ 2 года назад. Я на самом деле не использовал его ответ в то время, потому что мне не приходилось иметь дело с отрицательными цифрами. Использование replace не будет иметь никаких проблем. Я не уверен, почему вы прокомментировали это, кроме как привлечь мое внимание, чтобы отменить мой предыдущий ответ? – Paul Seeb 13 May 2014 в 21:22
  • 3
    Я не понимал, что это был ответ на ваш вопрос. Возвращаясь к моему комментарию, он произведет -10.1337 для приведенного выше примера. – devnull 13 May 2014 в 21:26
  • 4
    Изменено для работы с числами & gt; = 10 – Paul Seeb 13 May 2014 в 23:08

Я удивлен, что никто не предложил более математический способ сделать это:

n = 0.123456789
'.%d' % (n*1e4)

Мне гораздо приятнее. :)

Но интересно, что ваш самый быстрый.

$ python -mtimeit '".%d" % (0.123456789*1e4)'
1000000 loops, best of 3: 0.809 usec per loop
$ python -mtimeit '("%.4f"%(0.123456789)).lstrip("0")'
1000000 loops, best of 3: 0.209 usec per loop
$ python -mtimeit '("%.4f"%(0.123456789))[1:]'
10000000 loops, best of 3: 0.0723 usec per loop
2
ответ дан Ricardo Cruz 21 August 2018 в 20:31
поделиться

Строка str.format () стандартной библиотеки Python может использоваться для генерации преобразования строки значения float. Затем можно манипулировать строкой, чтобы сформировать конечный результат для положительного или отрицательного числа.

n = -.1234567890
print('{0}'.format('-' if n < 0 else '') + ('{:0.4}'.format(n).split('-')[1 if n < 0 else 0].lstrip('0')))
1
ответ дан StormCrow 21 August 2018 в 20:31
поделиться
0
ответ дан Brent Faust 4 November 2018 в 17:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: