Сохранить полную фамилию, получить инициалы имени (и второго имени, если оно есть) в столбце pandas - PullRequest
2 голосов
/ 26 февраля 2020

У меня есть pandas Датафрейм с колонкой, в которой указаны фамилия и имя нескольких теннисистов, например:

   | Player              | 
   |---------------------|
0  | 'Roddick Andy'      |
1  | 'Federer Roger'     |
2  | 'Tsonga Jo Wilfred  |

Я хочу сохранить полную фамилию и получить инициал имени и отчество, если есть. Поэтому столбец pandas должен выглядеть следующим образом:

   | Player            | 
   |-------------------|
0  | 'Roddick A.'      |
1  | 'Federer R.'      |
2  | 'Tsonga J.W.'     | N.B. J.W. with no space

У кого-нибудь есть предложения? Спасибо!

Ответы [ 3 ]

3 голосов
/ 26 февраля 2020

Вы можете использовать df.replace следующим образом:

import pandas as pd 
df = pd.DataFrame({'Player':['Roddick Andy', 'Federer Roger', 'Tsonga Jo Wilfred']})
df = df.replace(r'(?<=\s\w)\w+\s?', value = '.', regex = True)
print(df)

Регулярное выражение: (?<=\s\w)\w+\s?

  • \w+ - соответствует любому символу слова хотя бы единице
  • (?<=\s\w) - Положительный вид сзади (перед первым шагом должен стоять один пробел и любой отдельный символ слова
  • \s? - За первым шагом следует дополнительный пробел.

Результаты:

        Player
0   Roddick A.
1   Federer R.
2  Tsonga J.W.

РЕДАКТИРОВАТЬ:

Вариант 1:

Чтобы поменять местами два инициала, мы могли бы (сохранить идея использования регулярных выражений) добавьте еще df.replace, со вторым регулярным выражением.

import pandas as pd 
df = pd.DataFrame({'Player':['Roddick Andy', 'Federer Roger', 'Tsonga Jo Wilfred']})
df = df.replace(r'(?<=\s\w)\w+\s?', value = '.', regex = True)
df = df.replace(r'(.(?=\.)\.)(.(?=\.)\.)?', value = r'\2\1', regex = True)
print(df)

Регулярное выражение: (.(?=\.)\.)(.(?=\.)\.)?

  • (.(?=\.)\.) - Группа захвата 1: сопоставить любой символ (.), за которым следует (положительный взгляд) буквальную точку, включая сопоставление с точкой.
  • (.(?=\.)\.)? - Группа захвата 2: необязательный (?) захват g группа, совпадающая с тем же шаблоном, что и группа захвата 1.

Выше не очень динамично c. Но он будет работать нормально, если есть максимум две инициалы. Также возможно добавить его довольно легко, однако нижеприведенная опция будет более динамичной c.

Опция 2:

До Вы продолжаете, могу ли я упомянуть, что я довольно новичок в Python, поэтому я уверен, что то, что я сделал здесь, может быть сокращено / сделано намного проще.

Идея в том, чтобы split и дополнить фрейм данных, затем переверните все, кроме первого столбца, затем join затем верните их обратно в один столбец в фрейме данных, где мы затем можем применить df.replace.

import pandas as pd
df = pd.DataFrame({'Player':['Roddick Andy', 'Federer Roger', 'Tsonga Jo Wilfred']})
df = df.Player.str.split(None, expand=True).iloc[:, ::-1]
df = df[[list(df.columns)[-1]] + list(df.columns)[:-1]]
df = df[df.columns[0:]].apply(lambda x: ' '.join(x.dropna().astype(str)), axis=1)
df = df.replace(r'(?<=\s\w)\w+\s?', value = '.', regex = True)
print(df)

Результаты:

        Player
0   Roddick A.
1   Federer R.
2  Tsonga W.J.
2 голосов
/ 26 февраля 2020

Вот подход с str.extractall и groupby:

(df.Player
  .str.extractall('(?P<Surname>\w*)\s(?P<Name>\w*)')
  .groupby(level=0)
  .agg({'Surname':'first',
        'Name': lambda x: x.str[0].add('.').sum()
        })
  .agg(' '.join, axis=1)
)

Вывод:

0     Roddick A.
1     Federer R.
2    Tsonga J.W.
dtype: object
0 голосов
/ 26 февраля 2020

Предполагая, что каждая фамилия представляет собой одно слово, фамилия:

def shorten_name(name):
    name_as_list = name.split(" ")
    last_name = name_as_list[-1]
    first_names = ".".join([w[0] for w in name_as_list[:-1]]) + "."
    return (last_name, first_names)

, используя вот так:

last_name, first_names_shortened = shorten_name("Jo Wilfried Tsonga")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...