Есть ли способ, которым я могу извлечь числа из строки, окруженной различными суммами нулей с обеих сторон? - PullRequest
2 голосов
/ 14 июня 2019

Я должен извлечь сумму в долларах из одного столбца CSV. Сумма в долларах окружена нулями.

Доллары

1.   0000000000565400.60000000008289.116000 
2.   0000000466175218.82000043978794.228000
3.   0000000000005720.77000000000198.431000 

Из этих трех строк я бы хотел вытащить 565400.60, 466175218.82, 5720.77. Я не хочу / беспокоюсь о 8289.116, 43978794.228, 198.431.

dtype является ненулевым объектом. Я попытался преобразовать его в строку и извлечь первые 20 символов. Я также попытался заменить несколько нулей ничем. Очевидно, что я не могу избавиться от всех нулей из-за чисел типа 565400.60, где мне нужны нули. Даже если бы я смог преобразовать его в нужный мне тип d, я бы не знал, как вывести различное количество нулей.

dollars = str(dollars)
dollars = dollars.str.replace('0000000000','')

grab = dollars['Dollars'].astype(str).str[0:20]

Ожидаемое:

Dollars
------------
1. 565400.60
2. 466175218.82
3. 5720.77

Некоторые из моих ошибок:

TypeError: string indices must be integers
AttributeError: 'str' object has no attribute 'str'

Ответы [ 10 ]

3 голосов
/ 14 июня 2019

Вы можете использовать str.index для индексации, используя позицию первого .:

s = '0000000000565400.60000000008289.116000 '
s[:s.index('.')+3]
# '565400.60'
1 голос
/ 14 июня 2019

Вы можете попробовать regex и .str.extract для серии:

df.Dollars.str.extract(r'0+(\d+\.\d\d)')

Выход:

    0
0   565400.60
1   466175218.82
2   5720.77

Или, если вам нравится другая часть:

df.Dollars.str.extractall(r'0+(\d+\.\d\d)0+(\d+\.\d+)$'))

вывод:

                    0                1
  match                               
0 0         565400.60      8289.116000
1 0      466175218.82  43978794.228000
2 0           5720.77       198.431000
1 голос
/ 14 июня 2019

A pandas решение вашей проблемы может выглядеть примерно так:

>>> dollars = pd.Series(['0000000000565400.60000000008289.116000',
...                      '0000000466175218.82000043978794.228000',
...                      '0000000000005720.77000000000198.431000'])
>>> dollars.str[:19].astype(float).astype(str)
0        565400.6
1    466175218.82
2         5720.77
dtype: object
>>>
0 голосов
/ 14 июня 2019

Вы можете использовать регулярные выражения с шаблоном, например ^ 0 + (\ d +. \ D {2}) 0+ (при условии, что это всегда два числа после десятичной дроби).Вы можете проверить шаблон на https://regex101.com/. Вот код:

import re

string = ['0000000000565400.60000000008289.116000',
          '0000000466175218.82000043978794.228000',
          '0000000000005720.77000000000198.431000']

pattern = r'0+(?P<first_number>\d+.\d{2})0+'
for line in string:
    matches = re.search(pattern, str(line))
    print(matches['first_number'])


# 565400.60

Также, если вы работаете с блоком текста:

string = '''0000000000565400.60000000008289.116000\n
          0000000466175218.82000043978794.228000\n
          0000000000005720.77000000000198.431000\n'''

pattern = r'0+(\d+.\d{2})0+'
matches = re.findall(pattern, string, re.DOTALL)
print(matches)

# ['565400.60', '466175218.82', '5720.77']
0 голосов
/ 14 июня 2019

Поскольку вы знаете, что суммы указаны в долларах и центах, вы знаете, что у вас есть два десятичных знака. Просто возьмите большую часть строки ввода и удалите лишние нули.

line = "1.   0000000000565400.60000000008289.116000"
float_pair = line.split()[1]
decpt = float_pair.find('.')
amt_str = float_pair[:dec_pt+3]   # one extra for the decimal point
amt_no_zero = amt_str.lstrip('0')

Результат:

dec_pt = 16
amt_no_zero = '565400.60'
0 голосов
/ 14 июня 2019

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

>>> line = '0000000000565400.60000000008289.116000'
>>> first_number = line[:20]  # or :19 if you only want 2 digits after the dot
>>> first_number
'0000000000565400.600'

Поскольку вы работаете с денежными суммами, decimal.Decimalкласс хорошо использовать для извлечения суммы:

>>> from decimal import Decimal
>>> Decimal(first_number)
Decimal('565400.600')

, если вам нужно это как строка, тогда это просто:

>>> str(Decimal(first_number))
'565400.600'
0 голосов
/ 14 июня 2019

Вы можете использовать встроенную функцию 'find' для строки, затем подставить в строку строку с учетом позиции первой десятичной точки (плюс две позиции для центов). Затем приведите его как целое число или число с плавающей запятой, как вы хотите:

s = '00000123000.0000123000.000'
pos = s.find('.')
number = float(s[:pos+2])

Это должно работать, пока ваши объекты являются строками или могут быть преобразованы как строки.

0 голосов
/ 14 июня 2019

Это должно найти все ваши числа просто отлично - предостережение: возможно только 2 десятичных знака из-за фиксированной позиции после . для 1-го числа:

text = """
0000000000565400.60000000008289.116000
0000000466175218.82000043978794.228000
0000000000005720.77000000000198.431000
"""

for line in text.split(): 
    a = (line[:line.index(".")+3])  # find first ., take 2 digits after
    b = float(line[len(a):])        # take remainder after first find and conver to float
    a = float(a)                    # convert a to float (needed string for len())
    print(a,b)

Выход:

565400.6 8289.116
466175218.82 43978794.228
5720.77 198.431
0 голосов
/ 14 июня 2019

Предположим, вы хотите, чтобы первое число было до точки, а две цифры после. Тогда:

i = grab.find('.')
if i >= 0:
    grab = grab[:i + 3].lstrip('0')

будет производить то, что вы хотите.

0 голосов
/ 14 июня 2019

Просто сделайте что-то вроде:

Поиск первого ненулевого индекса символа (i0).

Поиск в первую очередь. индекс (i1).

Число, которое вы хотите = строка [i0: i1 + 3]

^ Это все питоническое - +3 б.п. +1 дополнительно и 2 цифры для центов, что, кажется, то, что вы хотите. Это также предполагает, что вы всегда хотите только первый номер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...