Условная замена запятой или пробела в числовой строке в столбце Pandas DataFrame без цикла - PullRequest
2 голосов
/ 06 апреля 2020

Иногда строковые числа в моих DataFrames содержат запятые, представляющие либо десятичную, либо отмечающую тысячу, а некоторые - нет. Фрейм данных - это пример диапазона ценовых форматов, которые я получаю через API и которые зависят от валюты. Это цены, а десятичные дроби всегда будут равны 2. Поэтому мне нужно вывести строковые цены в число с плавающей точкой, чтобы я мог их суммировать или разделить на другие кадры данных или использовать их для построения графиков. Я создал al oop для их замены, но есть ли более быстрый способ сделать это без l oop?

Мой DataFrame и рабочий l oop выглядит следующим образом:

data = {'amount': ['7,99', '6,99', '9.99', '-6,99', '1,000.00']}
df = pd.DataFrame(data)

fees = []
sales = []

for items in df['amount']:
    if items[-7:-6] == ',':
        items = float(items.replace(',', '').replace(' ',''))
    if items[-3:-2] == ',':
        items = float(items.replace(',', '.').replace(' ',''))
    items = float(items)
    if items <= 0:
        fees.append(items)
    else:
        sales.append(items)

Я пытался сделать это без l oop, но не могу понять, где я ошибся.

df["amount"] = np.where((df['amount'][-7:-6] == ','),
                       df["amount"][-7:-6].str.replace(',', '').replace(' ',''),
                       df["amount"])

df["amount"] = np.where((df['amount'][-3:-2] == ','),
                       df["amount"][-3:-2].str.replace(',', '').replace(' ',''),
                       df["amount"])

Любая помощь будет высоко ценится. Заранее спасибо

Ответы [ 3 ]

1 голос
/ 06 апреля 2020

Поскольку вы упоминаете, что последние две цифры являются десятичными точками, поэтому ',' необходимо заменить на '.', чтобы сделать его float, но у вас также есть некоторые значения, например 1,000.00, которые станут неактуальными, если ',' заменяется на '.', поэтому вы можете использовать regex, чтобы определить, какие значения следует заменить:

data = {'amount': ['7,99', '6,99', '9.99', '-6,99', '1,000.00']}
df = pd.DataFrame(data)
df

Сначала regex будет соответствовать всей строке с ',' и двумя десятичные точки, тогда функция замены заменит совпадение на '.' и захваченные значения (99 from ,99)

df['amount'] = df['amount'].str.replace(r'(,)(\d{2}$)',r'.\2') 
# here `r'.\2'`is second `captured group` in `regex`

Затем для преобразования 1,000.00 в float мы заменим ',' с пробелом

df['amount'] = df['amount'].str.replace(',','')

и затем преобразовать тип данных в float

df['amount'] = df['amount'].astype(float)

print(df)
    amount
0   799.00
1   699.00
2     9.99
3  -699.00
4  1000.00
1 голос
/ 06 апреля 2020

Вы можете использовать лямбды вместо numpy:

lambda1 = lambda items: float(str(items).replace(',', '').replace(' ','')) if str(items)[-7:-6] == ',' else items
lambda2 = lambda items: float(str(items).replace(',', '.').replace(' ','')) if str(items)[-3:-2] == ',' else items
to_float = lambda items: float(items)

df['amount_clean'] = df["amount"].map(lambda1).map(lambda2).map(to_float) 

=========================== ===================================================

Редактировать: что такое лямбды

В python лямбда-функции - это небольшие анонимные функции с одним выражением (см. https://www.w3schools.com/python/python_lambda.asp)

Пример с условием:

lambda x: x + 1 if x < 0 else x

Это эквивалентно:

def my_lambda_function(x):
    if x < 0:
        return x + 1
    else:
        return x

При передаче в столбец кадра данных pandas через функцию map, лямбда-выражение будет применяться к значению в каждая строка столбца.

Надеюсь, это поможет!

0 голосов
/ 06 апреля 2020

Попробуйте использовать split и join,

df.amount.str.split(',').str.join('').astype(float)

Вывод

0     799.00
1     699.00
2       9.99
3    -699.00
4    1000.00
Name: amount, dtype: float64
...