2017-10-03 1 views
0

Ich habe ein Dataset, in dem ich versuche, den einfachen Stadtnamen aus der längeren unordentlichen Version zu extrahieren, die hier gezeigt wird. Den meisten folgen Klammern "(. *", Aber einige folgen nicht diesem Muster und enden in ":" (siehe Zeile 200). Schließlich gibt es einige, die keine Klammern haben, sondern Teile mit einem Komma trennen ", . "(siehe Linie 240, 246)Nicht in der Lage, Zeichenfolge mit mehreren Sonderzeichen oder Muster in Python gleichzeitig zu extrahieren

           'Region' 
196 Boston (Boston University, Boston College, Bos... 
197   Bridgewater (Bridgewater State College)[2] 
198 Cambridge (Harvard University, Massachusetts I... 
199      Chestnut Hill (Boston College) 
200    The Colleges of Worcester Consortium: 
201        Dudley (Nichols College) 
240      Faribault, South Central College 
241 Mankato (Minnesota State University, Mankato),... 
242 Marshall (Southwest Minnesota State University... 
243 Moorhead (Minnesota State University, Moorhead... 
244   Morris (University of Minnesota Morris)[2] 
245 Northfield (Carleton College, St. Olaf College... 
246     North Mankato, South Central College 
247 St. Cloud (St. Cloud State University, The Col... 
248   St. Joseph (College of Saint Benedict)[2] 
249    St. Peter (Gustavus Adolphus College)[2] 

Was würde ich im Idealfall gerne sehen ist:

        'RegionName' 
    196         Boston 
    197       Bridgewater 
    198        Cambridge 
    199       Chestnut Hill 
    200 The Colleges of Worcester Consortium 
    201         Dudley 
    240        Faribault 
    241        Mankato 
    242        Marshall 
    243        Moorhead 
    244         Morris 
    245        Northfield 
    246       North Mankato 
    247        St. Cloud 
    248        St. Joseph 
    249        St. Peter 

Mein Code zur Zeit ist:

df['RegionName'] = df['Region'].str.extract('(.*)[:(,]', expand=False) 

Aber das gibt mir die seltsamen Ergebnis davon, dass die Klammern nicht in Ordnung gebracht werden ht:

196 Boston (Boston University, Boston College, Bos... 
197           Bridgewater 
198 Cambridge (Harvard University, Massachusetts I... 
199          Chestnut Hill 
200     The Colleges of Worcester Consortium 
201            Dudley 
240           Faribault 
241  Mankato (Minnesota State University, Mankato) 
242           Marshall 
243 Moorhead (Minnesota State University, Moorhead 
244           Morris 
245      Northfield (Carleton College 
246          North Mankato 
247    St. Cloud (St. Cloud State University 
248          St. Joseph 
249          St. Peter 

Ich habe auch versucht:

df['RegionName'] = df['Region'].str.extract('(.*)[ (.*|:|,]', expand=False) 

Ich bin nicht sicher, wie genau die Zeichenfolge zu extrahieren alle drei Muster zur gleichen Zeit verwenden. Wäre offen für eine Zwei-Linien-Lösung. Dank (Entschuldigung, wenn diese schlecht formatiert!)

Antwort

1

Sie können nur extrahieren alle 0 oder mehr Zeichen andere als :, , oder ( am Anfang eines Strings mit

df['RegionName'] = df['Region'].str.extract(r'^([^:(,]*)\b', expand=False) 

Wenn Sie mit Python 2.x arbeiten, verwenden (?u) am Anfang das Muster, so dass die Wortgrenze \b auch die richtigen Stellen in einer Unicode-Zeichenfolge übereinstimmen konnte.

Einzelheiten

  • ^ - Beginn einer Zeichenfolge
  • ([^:(,]*) - Gruppe 1: Null oder mehr (*) aufeinanderfolgenden Vorkommen von jedem char andere als (die [^...] bildet eine negiert Zeichenklasse) :, ( und ,.
  • \b - eine Wortgrenze.

Siehe regex demo und ein Demo-Python 3 unten:

>>> from pandas import DataFrame 
>>> import pandas as pd 
>>> item_list = ['Boston (Boston University, Boston College, Bos...','Bridgewater (Bridgewater State College)[2]','Cambridge (Harvard University, Massachusetts I...','Chestnut Hill (Boston College)','The Colleges of Worcester Consortium:','Dudley (Nichols College)','Faribault, South Central College','Mankato (Minnesota State University, Mankato),...','Marshall (Southwest Minnesota State University...','Moorhead (Minnesota State University, Moorhead...','Morris (University of Minnesota Morris)[2]','Northfield (Carleton College, St. Olaf College...','North Mankato, South Central College','St. Cloud (St. Cloud State University, The Col...','St. Joseph (College of Saint Benedict)[2]','St. Peter (Gustavus Adolphus College)[2]'] 
>>> df = pd.DataFrame(item_list, columns=['Region']) 
>>> df['RegionName'] = df['Region'].str.extract(r'^([^:(,]*)\b', expand=False) 
>>> df['RegionName'] 

           RegionName 
0         Boston 
1       Bridgewater 
2        Cambridge 
3       Chestnut Hill 
4 The Colleges of Worcester Consortium 
5         Dudley 
6        Faribault 
7        Mankato 
8        Marshall 
9        Moorhead 
10        Morris 
11       Northfield 
12       North Mankato 
13        St. Cloud 
14       St. Joseph 
15        St. Peter 
>>> 
+0

Danke für diese Antwort. Etwas, das ich im Dataset nicht gezeigt habe, ist, dass dort Zustände wie "Michigan \ [edit \]" aufgelistet sind, die ich löschen möchte. Früher hat der 'str.extract' diese zu NaN's gemacht und so würde ich diese fallenlassen. Aber Ihre Methode lässt sie im Datensatz (sie werden "Michigan [bearbeiten]). Wie würdest du dich darauf einstellen? Teil 2: Ich habe versucht:. 'df [ 'Region'] = df [ 'Region'] str.replace (r '(^ * \ [edit $)', np.nan)' , die gedreht alles in NaNs. Warum sollte das sein? Stattdessen ersetzte ich es durch eine leere Zelle und ersetzte dann leer bis NaN. Scheint jedoch ineffizient. Thx – Vicki

+0

Versuchen Sie ['r '^ ([^: (,] *?) \ S * [: (,]''] (https://regex101.com/r/asdHNp/1) und verwenden Sie Ihre vorherige 'dropna "Ansatz. –

0

Mit diesem regulären Ausdruck:

([\w\s.]+)(?<!\s) 

Sie können den negativen Blick hinter (?<!\s) am Ende entfernen, wenn Sie nicht über Hinter weißen Räumen ist es egal.

1

Da Sie nur drei mögliche Trennzeichen haben, können Sie die verketteten split() nutzen, da split die unmodifizierte Zeichenkette zurückgibt, wenn das Trennzeichen nicht gefunden wird.

>>> s = """196 Boston (Boston University, Boston College, Bos... 
... 197   Bridgewater (Bridgewater State College)[2] 
... 198 Cambridge (Harvard University, Massachusetts I... 
... 199      Chestnut Hill (Boston College) 
... 200    The Colleges of Worcester Consortium: 
... 201        Dudley (Nichols College) 
... 240      Faribault, South Central College 
... 241 Mankato (Minnesota State University, Mankato),... 
... 242 Marshall (Southwest Minnesota State University... 
... 243 Moorhead (Minnesota State University, Moorhead... 
... 244   Morris (University of Minnesota Morris)[2] 
... 245 Northfield (Carleton College, St. Olaf College... 
... 246     North Mankato, South Central College 
... 247 St. Cloud (St. Cloud State University, The Col... 
... 248   St. Joseph (College of Saint Benedict)[2] 
... 249    St. Peter (Gustavus Adolphus College)[2]""" 
>>> for i in s.split('\n'): 
... number, text = i.split('(')[0].split(',')[0].split(':')[0].split(' ',1) 
... print('{} {}'.format(number, text.strip())) 
... 
196 Boston 
197 Bridgewater 
198 Cambridge 
199 Chestnut Hill 
200 The Colleges of Worcester Consortium 
201 Dudley 
240 Faribault 
241 Mankato 
242 Marshall 
243 Moorhead 
244 Morris 
245 Northfield 
246 North Mankato 
247 St. Cloud 
248 St. Joseph 
249 St. Peter 

können Sie df.apply verwenden die gleiche Transformation für die Saiten zu tun.

+0

Ich glaube nicht, die Zeilennummer und Polsterung ist Teil der Daten - es ist, wie einfach die Daten formatiert wird, wenn auf die Konsole ausgegeben . – Mark

Verwandte Themen