Espressione regolare per ripulire i nomi

Oct 08 2020

Ho due dataframe di nomi. Il dataframe è più lungo, ma sto usando top3 come esempi.

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

Devo estrarre il primo nome in quei due dfs, come posso estrarli in un'unica espressione regolare.

The return should be 
list 1
JOSHEPH 
MIMI
WANT

list 2
DNNIES
LINDA
FARLEY

Il mio codice attuale sembra come re.search(r'(?<=,)\w+', df['name']), ma non ha restituito il nome corretto. È possibile scrivere due codici di espressioni regolari in Python per estrarre quei nomi?

Risposte

1 alani Oct 08 2020 at 19:38

Sembra che ciò che si desidera cercare qui è la prima sequenza di caratteri di parola che non dispongono di un qualsiasi punto virgola dopo sulla linea, piuttosto che uno che non ha una virgola prima di esso. Quindi, invece di una tua affermazione positiva, sembra che vorrai un'affermazione negativa.

Prova a usare come regex:

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

Applicalo usando:

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

Applicando quanto sopra a questo dataframe di esempio:

                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

Uso

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

Vedi la prova

Spiegazione

--------------------------------------------------------------------------------
  (?:                      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