как изменить конкретную вложенную строку в сжатом виде в python?

#python #pandas #string #lambda #street-address

#python #pandas #строка #лямбда #уличный адрес

Вопрос:

Я хочу уточнить набор данных:

 df = pd.DataFrame({'address':['123 AB 45 CD','123 AB 45TH CD','123 AB 12ND CD','123 AB 12 CD','123 AB 12TH CD']})
 

в:

 df = pd.DataFrame({'address':['123 AB 45TH CD','123 AB 45TH CD','123 AB 12ND CD','123 AB 12ND CD','123 AB 12ND CD']})
 

Я просто выясняю одну часть утомительным способом:

 def action(name):
    middle = name.split(" ")[2]
    if middle.isnumeric():
        if int(middle[-1]) == 1:
            name = name.replace(middle, middle 'st')
        elif int(middle[-1]) == 2:
            name = name.replace(middle, middle 'nd')
        elif int(middle[-1]) == 3:
            name = name.replace(middle, middle 'rd')
        else:
            name = name.replace(middle, middle 'th')
    return name
    
test['street'] = test['street'].apply(lambda x: action(x))
 

Может ли кто-нибудь переписать ее в сжатом виде и добавить условие с 12-го по 12-е?
Я думаю

 ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(n//10%10!=1)*(n%10<4)*n%10::4])
 

и лямбда-функция может быть полезной, но, как более новая, не смогла разобраться.
Спасибо!

Комментарии:

1. Логика кажется ошибочной, что, если число равно 11-13?

2. Да, это правда. Как уточнить его с помощью «порядкового номера»?

Ответ №1:

Может быть, использовать регулярное выражение, чтобы получить немного более согласованный вывод?

 import re
import pandas

# Your dataset
df = pandas.DataFrame(
    {
        "address": [
            "123 AB 45 CD",
            "123 AB 45TH CD",
            "123 AB 12ND CD",
            "123 AB 12 CD",
            "123 AB 12TH CD",
        ]   [
            f"123 AB {i} CD" for i in range(1, 100)  # Generate all options from 1 to 100
        ]
    }
)


def action(name):

    # Pick the name appart
    match = re.search(
        r"^(?P<before>d sw )s(?P<number>d )(?P<extension>w*)s(?P<after>w )$",
        name,
    )

    # Impossible to do anything, return as is with a warning
    if match is None:
        print("Impossible to parse", name)
        return name

    # Extract the elements of the name
    before = match.group("before")
    number = int(match.group("number"))
    extension = match.group("extension")
    after = match.group("after")

    # Check if the name already has an extension
    if extension != "":
        return name

    # Return the formatted string (using your ordinal function)
    return f"{before} {number}{'TSNRHTDD'[(number//10%10!=1)*(number%10<4)*number%10::4]} {after}"


df["street"] = df["address"].apply(lambda x: action(x))
print(df["street"].to_list())
 

Вывод:

 ['123 AB 45TH CD',
 '123 AB 45TH CD',
 '123 AB 12ND CD',
 '123 AB 12TH CD',
 '123 AB 12TH CD',
 '123 AB 1ST CD',
 '123 AB 2ND CD',
 '123 AB 3RD CD',
 '123 AB 4TH CD',
 '123 AB 5TH CD',
 '123 AB 6TH CD',
 '123 AB 7TH CD',
 '123 AB 8TH CD',
 '123 AB 9TH CD',
 '123 AB 10TH CD',
 '123 AB 11TH CD',
 '123 AB 12TH CD',
 '123 AB 13TH CD',
 '123 AB 14TH CD',
 '123 AB 15TH CD',
 '123 AB 16TH CD',
 '123 AB 17TH CD',
 '123 AB 18TH CD',
 '123 AB 19TH CD',
 '123 AB 20TH CD',
 '123 AB 21ST CD',
 '123 AB 22ND CD',
 '123 AB 23RD CD',
 '123 AB 24TH CD',
 '123 AB 25TH CD',
 '123 AB 26TH CD',
 '123 AB 27TH CD',
 '123 AB 28TH CD',
 '123 AB 29TH CD',
 '123 AB 30TH CD',
 '123 AB 31ST CD',
 '123 AB 32ND CD',
 '123 AB 33RD CD',
 '123 AB 34TH CD',
 '123 AB 35TH CD',
 '123 AB 36TH CD',
 '123 AB 37TH CD',
 '123 AB 38TH CD',
 '123 AB 39TH CD',
 '123 AB 40TH CD',
 '123 AB 41ST CD',
 '123 AB 42ND CD',
 '123 AB 43RD CD',
 '123 AB 44TH CD',
 '123 AB 45TH CD',
 '123 AB 46TH CD',
 '123 AB 47TH CD',
 '123 AB 48TH CD',
 '123 AB 49TH CD',
 '123 AB 50TH CD',
 '123 AB 51ST CD',
 '123 AB 52ND CD',
 '123 AB 53RD CD',
 '123 AB 54TH CD',
 '123 AB 55TH CD',
 '123 AB 56TH CD',
 '123 AB 57TH CD',
 '123 AB 58TH CD',
 '123 AB 59TH CD',
 '123 AB 60TH CD',
 '123 AB 61ST CD',
 '123 AB 62ND CD',
 '123 AB 63RD CD',
 '123 AB 64TH CD',
 '123 AB 65TH CD',
 '123 AB 66TH CD',
 '123 AB 67TH CD',
 '123 AB 68TH CD',
 '123 AB 69TH CD',
 '123 AB 70TH CD',
 '123 AB 71ST CD',
 '123 AB 72ND CD',
 '123 AB 73RD CD',
 '123 AB 74TH CD',
 '123 AB 75TH CD',
 '123 AB 76TH CD',
 '123 AB 77TH CD',
 '123 AB 78TH CD',
 '123 AB 79TH CD',
 '123 AB 80TH CD',
 '123 AB 81ST CD',
 '123 AB 82ND CD',
 '123 AB 83RD CD',
 '123 AB 84TH CD',
 '123 AB 85TH CD',
 '123 AB 86TH CD',
 '123 AB 87TH CD',
 '123 AB 88TH CD',
 '123 AB 89TH CD',
 '123 AB 90TH CD',
 '123 AB 91ST CD',
 '123 AB 92ND CD',
 '123 AB 93RD CD',
 '123 AB 94TH CD',
 '123 AB 95TH CD',
 '123 AB 96TH CD',
 '123 AB 97TH CD',
 '123 AB 98TH CD',
 '123 AB 99TH CD']