2017-03-31 2 views
1

Ich versuche, alle Wörter mit weniger als 4 Zeichen aus jedem Skalarwert in einer Pandas-Serie zu entfernen. Was ist der beste Weg, es zu tun? Hier ist mein gescheiterter Versuch:Entfernen Sie Wörter weniger als 4 Zeichen aus Pandas Series

df['text'] = df['text'].str.join(word for word in df['text'].str.split() if len(word)>3) 

ich die folgende Fehlermeldung angezeigt:

AttributeError: 'generator' object has no attribute 'join'

ich anhand meines Versuch aus diesem Beitrag in Bezug auf das gleiches in einem String: Remove small words using Python

Randbemerkung: Wenn es besser ist, meine Wörter zu symbolisieren, bevor Sie sie mit weniger als 4 Zeichen entfernen, lassen Sie es mich bitte wissen.

EDIT: Jeder skalare Wert enthält Sätze, also möchte ich für alle Wörter weniger als eine Länge von 4 innerhalb des Wertes entfernen.

+0

halte ich würde @piRSquared akzeptieren 's Lösung. Es ist mehr "pandonisch", ich fühle mich. Es wäre jedoch interessant, einige Leistungsvergleiche zu machen und den Schnellsten zu gewinnen! –

Antwort

2

Mit Regex mit .str.findall und .str.join erscheint am schnellsten zu sein:

df['text'].str.findall('\w{4,}').str.join(' ') 

Timings

Unter Verwendung der folgenden Einstellung:

df = pd.DataFrame({'text':["The quick brown fox", "jumped over the lazy dog", "foo bar baz", 'words exceeding desired length']}) 
df = pd.concat([df]*10**4, ignore_index=True) 

def pir2(df): 
    t = df.text.str.split(expand=True).stack() 
    return t.loc[t.str.len() >= 4].groupby(level=0).apply(' '.join) 

ich die folgenden Timings erhalten:

%timeit df['text'].str.findall('\w{4,}').str.join(' ') 
10 loops, best of 3: 44.8 ms per loop 

%timeit df.text.apply(lambda i: ' '.join(filter(lambda j: len(j) > 3, i.split()))) 
10 loops, best of 3: 79.3 ms per loop 

%timeit df['text'].str.split().map(lambda sl: " ".join(s for s in sl if len(s) > 3)) 
10 loops, best of 3: 87.2 ms per loop 

%timeit pir2(df) 
1 loop, best of 3: 2.87 s per loop 
3

Sie können etwas tun:

>>> df = pd.DataFrame({'text':["The quick brown fox", "jumped over the lazy dog"]}) 
>>> df 
         text 
0  The quick brown fox 
1 jumped over the lazy dog 
>>> df['text'].str.split().map(lambda sl: " ".join(s for s in sl if len(s) > 3)) 
0   quick brown 
1 jumped over lazy 
Name: text, dtype: object 

Aber ehrlich gesagt, ich bleibe in der Regel zu Vanille Python für Textverarbeitungspipelines. pandas Datenstrukturen spielen nicht gut mit Text. Zumindest verlieren Sie die Speicher-/Geschwindigkeitsvorteile von numpy/pandas.

+1

Beat mich dazu :-) +1 – bernie

0

df.test.apply(lambda i: ' '.join(filter(lambda j: len(j) > 3, i.split())))

1

Versuchen Betrachten @ juanpa.arrivillaga der dataframedf

df = pd.DataFrame({'text':["The quick brown fox", "jumped over the lazy dog"]}) 

Dann können wir

t = df.text.str.split(expand=True).stack() 
t.loc[t.str.len() >= 4].groupby(level=0).apply(' '.join) 

0   quick brown 
1 jumped over lazy 
dtype: object 
+1

Sehr schön, obwohl, bis Sie 'apply' verwenden müssen :(. Ich immer noch' Pandas' ist das falsche Werkzeug für Text-Preprocessing. –

+0

@ juanpa.arrivillaga was tun Sie Vorschlag? – piRSquared

+1

Vanilla Python. Sobald Sie einen Datenrahmen haben, der "Objekt" dtype ist, haben Sie die Geschwindigkeit/Speichereffizienz von 'numpy' /' pandas' aufgegeben. Manchmal ist das OK, weil die "Panel" -Abstraktion immer noch ist nützlich, und es gibt eine Menge praktischer Routinen, die in 'pandas' Datenstrukturen eingebaut sind, aber das ist wirklich nicht der Fall für Text.Der Großteil meiner Text-Vorverarbeitung findet in Vanille Python statt, was gewöhnlich zu einer spärlichen Darstellung führt, die ich Feed in 'sklearn' Vektorisierer, um featurized, spärliche' numpy' Arrays zu erhalten.Aber * wenn * ich Pandas benutzen würde, würde ich das wählen :) –

Verwandte Themen