Expressão regular para limpar nomes

Oct 08 2020

Eu tenho dois dataframes de nomes. O dataframe é mais longo, mas estou usando top3 como exemplos.

First list name examples: 
JOSEPH W. JOHN
MIMI N. ALFORD
WANG E. Li

Second list name examples:
AAMIR, DENNIS M
MAHAMMED, LINDA X
ABAD, FARLEY J

Preciso extrair o primeiro nome nesses dois dfs, como posso extraí-los em uma expressão regular.

The return should be 
list 1
JOSHEPH 
MIMI
WANT

list 2
DNNIES
LINDA
FARLEY

Meu código atual parece re.search(r'(?<=,)\w+', df['name']), mas não retornou o nome correto. É possível escrever dois códigos de expressão regular em Python para extrair esses nomes?

Respostas

1 alani Oct 08 2020 at 19:38

Parece que o que você quer olhar para aqui é a primeira seqüência de caracteres de palavras que não têm um lugar vírgula após -lo na linha, ao invés de um que não tem uma vírgula antes dele. Portanto, em vez de sua afirmação positiva de olhar para trás, parece que você deseja uma afirmação de olhar para trás negativa.

Tente usar como sua regex:

r'\w+(?!.*,)'

Aplique isso usando:

df['name'].apply(lambda name:re.search(r'\w+(?!.*,)',name).group())

Aplicando o acima para este exemplo de dataframe:

                name   foo
0     JOSEPH W. JOHN     1
1     MIMI N. ALFORD     3
2         WANG E. Li     3
3    AAMIR, DENNIS M     3
4  MAHAMMED, LINDA X     3
5     ABAD, FARLEY J     3

dá:

0    JOSEPH
1      MIMI
2      WANG
3    DENNIS
4     LINDA
5    FARLEY
2 RyszardCzech Oct 08 2020 at 20:21

Usar

df['First Name'] = df['name'].str.extract(r'(?:(?<=^(?!.*,))|(?<=, ))([A-Z]+)', expand=False)

Veja a prova

Explicação

--------------------------------------------------------------------------------
  (?:                      group, but do not capture:
--------------------------------------------------------------------------------
    (?<=                     look behind to see if there is:
--------------------------------------------------------------------------------
      ^                        the beginning of the string
--------------------------------------------------------------------------------
      (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
        .*                       any character except \n (0 or more
                                 times (matching the most amount
                                 possible))
--------------------------------------------------------------------------------
        ,                        ','
--------------------------------------------------------------------------------
      )                        end of look-ahead
--------------------------------------------------------------------------------
    )                        end of look-behind
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    (?<=                     look behind to see if there is:
--------------------------------------------------------------------------------
      ,                        ', '
--------------------------------------------------------------------------------
    )                        end of look-behind
--------------------------------------------------------------------------------
  )                        end of grouping
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    [A-Z]+                   any character of: 'A' to 'Z' (1 or more
                             times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \1