Лямбда-функция для извлечения чисел из указанной c строки - PullRequest
0 голосов
/ 18 июня 2020

Есть ли способ создать функцию, которая ищет строку во всем фрейме данных, когда она находит указанную строку и извлекает из нее исходящие числа?

ex фрейм данных:

1                       2                               3                       4 
6/9/2020 1 Per Page  IRES MLS  : 91 PRICE: $59,900    Beautiful Views Sold   Total Concession: $2000
6/9/2020 1 Per Page  IRES MLS : 906 PRICE: $350,000   Fast Seller!           Total Concession: $5029
6/9/2020 1 Per Page  IRES MLS : 908 PRICE: $360,000   Total Concession: $9000

Мне удалось создать функцию, которая сообщает, существует эта строка или нет, и возвращает логическое значение

#searches the dataframe for the words Total Concession and returns if True
df['Concession'] = df.apply(lambda row: row.astype(str).str.contains('Total Concession', regex=True).any(), axis=1)

Total Concession не имеет одного столбца в созданном фрейме данных, он находится в разных столбцах в фрейм данных. Мне было интересно, есть ли способ сделать так, чтобы он возвращал это.

Concession
2000
5029
9000

Ответы [ 3 ]

1 голос
/ 19 июня 2020

Потому что то, что вы ищете, находится в конце каждого столбца. Объедините все строковые столбцы в столбец с именем text, используя метод .join()

Одна строка кода

df['text'] = df.apply(''.join, axis=1).str.split('[$]').str[-1]

В качестве альтернативы, если хотите использовать Regex, можете попробовать

#df['text'] = df.apply(''.join, axis=1).str.extract('((?<=Concession:).*$)')#Use positive look ahead.Basically anything after Concession:
#df['text']=df['text'].str.replace('$','')#Replace $ with a white space




        1                                           2  \
0  6/9/2020   1 Per Page  IRES MLS  : 91 PRICE: $59,900   
1  6/9/2020  1 Per Page  IRES MLS : 906 PRICE: $350,000   
2  6/9/2020  1 Per Page  IRES MLS : 908 PRICE: $360,000   

                         3                        4  \
0     Beautiful Views Sold  Total Concession: $2000   
1             Fast Seller!  Total Concession: $5029   
2  Total Concession: $9000  Total Concession: $9000   

                                                text concession  
0  6/9/20201 Per Page  IRES MLS  : 91 PRICE: $59,...       2000  
1  6/9/20201 Per Page  IRES MLS : 906 PRICE: $350...       5029  
2  6/9/20201 Per Page  IRES MLS : 908 PRICE: $360...       9000  
0 голосов
/ 19 июня 2020

Используйте pandas .Series.str.findall с положительным просмотром назад:

  • '(?<= \$)[\d,]+
    • enter image description here
    • Это позволит извлечь совпадение из любого места в строке.
import pandas as pd

# setup dataframe
data = {'Date': ['6/9/2020', '6/9/2020', '6/9/2020'],
        'Price': ['1 Per Page  IRES MLS  : 91 PRICE: $59,900', '1 Per Page  IRES MLS : 906 PRICE: $350,000', '1 Per Page  IRES MLS : 908 PRICE: $360,000'],
        'Description': ['Beautiful Views Sold', 'Fast Seller!', ''],
        'Total Concession': ['Total Concession: $2000', 'Total Concession: $5029', 'Total Concession: $9000']}

df = pd.DataFrame(data)

       Date                                       Price           Description         Total Concession
0  6/9/2020   1 Per Page  IRES MLS  : 91 PRICE: $59,900  Beautiful Views Sold  Total Concession: $2000
1  6/9/2020  1 Per Page  IRES MLS : 906 PRICE: $350,000          Fast Seller!  Total Concession: $5029
2  6/9/2020  1 Per Page  IRES MLS : 908 PRICE: $360,000                        Total Concession: $9000

# extract numbers from columns
for c in df.columns:
    df[f'extracted {c}'] = df[c].str.findall('(?<= \$)[\d,]+').explode().str.replace(',', '')

# columns with no match, like Description, will be all NaN, so drop them
df.dropna(axis=1, inplace=True, how='all')

# output
       Date                                       Price           Description         Total Concession extracted Price extracted Total Concession
0  6/9/2020    1 Per Page $59,798 IRES MLS  : 91 PRICE:  Beautiful Views Sold  Total Concession: $2000           59798                       2000
1  6/9/2020  1 Per Page  IRES MLS : 906 PRICE: $350,000          Fast Seller!  Total Concession: $5029          350000                       5029
2  6/9/2020  1 Per Page  IRES MLS : 908 PRICE: $360,000                        Total Concession: $9000          360000                       9000

# drop or rename other columns as needed

Только общая уступка

  • '(?<=Total Concession: \$)[\d,]+'
    • enter image description here
    • Будет извлечены только числа, перед которыми стоит 'Total Concession: $'
for c in df.columns:
    df[f'extracted {c}'] = df[c].str.findall('(?<=Total Concession: \$)[\d,]+').explode().str.replace(',', '')

df.dropna(axis=1, inplace=True, how='all')

# output
       Date                                       Price           Description         Total Concession extracted Total Concession
0  6/9/2020   1 Per Page  IRES MLS  : 91 PRICE: $59,900  Beautiful Views Sold  Total Concession: $2000                       2000
1  6/9/2020  1 Per Page  IRES MLS : 906 PRICE: $350,000          Fast Seller!  Total Concession: $5029                       5029
2  6/9/2020  1 Per Page  IRES MLS : 908 PRICE: $360,000                        Total Concession: $9000                       9000

Надежный пример

# setup dataframe
data = {'Date': ['6/9/2020', '6/9/2020', '6/9/2020'],
        'Price': ['1 Per Page  IRES MLS  : 91 PRICE: $59,900', '1 Per Page  IRES MLS : 906 PRICE: $350,000', '1 Per Page  IRES MLS : 908 PRICE: $360,000'],
        'Description': ['Beautiful Views Sold', 'Fast Seller!', ''],
        'Total Concession': ['Nothing to see here', 'Total Concession: $5029', 'Total Concession: $9000'],
        'Test1': ['A bunch Total Concession: $6,399 of random stuff', 'stuff1', 'stuff2']}

df = pd.DataFrame(data)

       Date                                       Price           Description         Total Concession                                             Test1
0  6/9/2020   1 Per Page  IRES MLS  : 91 PRICE: $59,900  Beautiful Views Sold      Nothing to see here  A bunch Total Concession: $6,399 of random stuff
1  6/9/2020  1 Per Page  IRES MLS : 906 PRICE: $350,000          Fast Seller!  Total Concession: $5029                                            stuff1
2  6/9/2020  1 Per Page  IRES MLS : 908 PRICE: $360,000                        Total Concession: $9000                                            stuff2


for c in df.columns:
    df[f'extracted {c}'] = df[c].str.findall('(?<=Total Concession: \$)[\d,]+').explode().str.replace(',', '')

df.dropna(axis=1, inplace=True, how='all')


# list of all extracted columns
extracted_columns = [x for x in df.columns if 'extracted' in x]

# sum all extracted columns
df['all concessions'] = df[extracted_columns].astype(float).sum(axis=1)

# drop the extracted columns
df.drop(columns=extracted_columns, inplace=True)

# print df
       Date                                       Price           Description         Total Concession                                             Test1  all concessions
0  6/9/2020   1 Per Page  IRES MLS  : 91 PRICE: $59,900  Beautiful Views Sold      Nothing to see here  A bunch Total Concession: $6,399 of random stuff           6399.0
1  6/9/2020  1 Per Page  IRES MLS : 906 PRICE: $350,000          Fast Seller!  Total Concession: $5029                                            stuff1           5029.0
2  6/9/2020  1 Per Page  IRES MLS : 908 PRICE: $360,000                        Total Concession: $9000                                            stuff2           9000.0
0 голосов
/ 19 июня 2020

Это один из способов; предостережение в том, что есть только один столбец, который может иметь полную уступку - вам, возможно, придется переформулировать свой вопрос, если вы чувствуете, что более одного столбца могут содержать полную уступку

import re
def extract(text_box):

    #extract text that has Total Concession
    for entry in text_box:
        if entry is None:
            continue
        if "Total Concession" in entry:
            text = entry
    match = re.search("(?<=Total Concession:).*", text)
    res = match.group(0).strip().strip("$")

    return res

Функция Apply:

df['extract'] = [extract(lst) for lst in df.to_numpy()]

1   2   3   4   extract
0   6/9/2020 1 Per Page IRES MLS    : 91 PRICE: $59,900 Beautiful Views Sold Total Concession: $2000    2000
1   6/9/2020 1 Per Page IRES MLS : 906 PRICE: $350,000  Fast Seller!    Total Concession: $5029 5029
2   6/9/2020 1 Per Page IRES MLS : 908 PRICE: $360,000  Total Concession: $9000 None    9000
...