Expressão regular para limpar nomes
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
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
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