2016-09-12 1 views
2

Ich übe mich auf NLTK zu verwenden, um bestimmte Features aus rohen Tweets zu entfernen und in der Hoffnung, Tweets zu entfernen, die (irrelevant) sind (z. B. leere Tweets oder einzelne Wort Tweets). Es scheint jedoch, dass einige der einzelnen Wort Tweets nicht entfernt werden. Ich habe auch ein Problem damit, dass ich keine Stoppwörter entfernen kann, die entweder am Anfang oder am Ende eines Satzes stehen.Text Vorverarbeitung mit NLTK

Irgendwelche Ratschläge? Im Moment hoffe ich, einen Satz als eine Ausgabe statt als eine Liste von in Token zerlegten Wörtern zurück zu geben.

Jeder andere Kommentar zur Verbesserung des Codes (Bearbeitungszeit, Eleganz) sind willkommen.

import string 
import numpy as np 
import nltk 
from nltk.corpus import stopwords 

cache_english_stopwords=stopwords.words('english') 
cache_en_tweet_stopwords=stopwords.words('english_tweet') 

# For clarity, df is a pandas dataframe with a column['text'] together with other headers. 

def tweet_clean(df): 
    temp_df = df.copy() 
    # Remove hyperlinks 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('https?:\/\/.*\/\w*', '', regex=True) 
    # Remove hashtags 
    # temp_df.loc[:,"text"]=temp_df.loc[:,"text"].replace('#\w*', '', regex=True) 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('#', ' ', regex=True) 
    # Remove citations 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('\@\w*', '', regex=True) 
    # Remove tickers 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('\$\w*', '', regex=True) 
    # Remove punctuation 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('[' + string.punctuation + ']+', '', regex=True) 
    # Remove stopwords 
    for tweet in temp_df.loc[:,"text"]: 
     tweet_tokenized=nltk.word_tokenize(tweet) 
     for w in tweet_tokenized: 
      if (w.lower() in cache_english_stopwords) | (w.lower() in cache_en_tweet_stopwords): 
       temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('[\W*\s?\n?]'+w+'[\W*\s?]', ' ', regex=True) 
       #print("w in stopword") 
    # Remove quotes 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('\&*[amp]*\;|gt+', '', regex=True) 
    # Remove RT 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('\s+rt\s+', '', regex=True) 
    # Remove linebreak, tab, return 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('[\n\t\r]+', ' ', regex=True) 
    # Remove via with blank 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('via+\s', '', regex=True) 
    # Remove multiple whitespace 
    temp_df.loc[:, "text"] = temp_df.loc[:, "text"].replace('\s+\s+', ' ', regex=True) 
    # Remove single word sentence 
    for tweet_sw in temp_df.loc[:, "text"]: 
     tweet_sw_tokenized = nltk.word_tokenize(tweet_sw) 
     if len(tweet_sw_tokenized) <= 1: 
      temp_df.loc["text"] = np.nan 
    # Remove empty rows 
    temp_df.loc[(temp_df["text"] == '') | (temp_df['text'] == ' ')] = np.nan 
    temp_df = temp_df.dropna() 
    return temp_df 
+0

Bitte bearbeiten ** Ihre Frage ** zu erklären, dass ' df' ist ein Pandas Datenrahmen (wie ich aus deinen Kommentaren erfahren habe). Idealerweise sollten Sie ein paar Codezeilen hinzufügen, damit ein vollständiges Snippet erstellt wird, das ausgeführt werden kann, wenn Ihnen jemand eine bessere Antwort geben möchte. Und wenn Sie entscheiden, dass Ihre eigene Selbst-Antwort Ihr Problem gelöst hat, sollten Sie es schließlich als "akzeptiert" markieren. (Aber zuerst würde ich deine Frage klären und auf bessere Antworten warten). – alexis

Antwort

3

Was ist df? eine Liste von Tweets? Sie sollten vielleicht in Betracht ziehen, den Tweet nacheinander zu putzen und nicht als eine Liste von Tweets. Es wäre einfacher, eine Funktion tweet_cleaner(single_tweet) zu haben.

nltk stellt TweetTokenizer zur Verfügung, um die Tweets zu bereinigen.

Die "re" package bietet gute Lösungen für die Verwendung von Regex.

ich Rat Sie eine Variable für eine einfachere Verwendung von temp_df.loc[:, "text"]

Löschen Stoppwörter in einem Satz erstellen beschrieben [hier] (Stopword removal with NLTK): clean_wordlist = [i for i in sentence.lower().split() if i not in stopwords]

Wenn Sie regex verwenden möchten (mit dem re-Paket), können Sie

  1. einen RegexMuster erstellen alle Stoppwörter zusammengesetzt (aus der tweet_clean-Funktion): stop_pattern = re.compile('|'.join(stoplist)(?siu))
    (? Siu) für mehrzeilige, ignorecase, Unicode

  2. und dieses Muster verwendet eine beliebige Zeichenfolge zu reinigen clean_string = stop_pattern.sub('', input_string)

(Sie die 2 Dispositionen verketten können, wenn getrennt solche mit ist nicht erforderlich)

1 Wörter entfernen twittern Sie nur die eine längste als 1 Wort halten könnte:
if len(tweet_sw_tokenized) >= 1: kept_ones.append(tweet_sw)

+0

Aus meinem Durcheinander von Codes kopiert. df ist ein pandas.dataframe und darin befindet sich eine "text" -Spalte. Stellen Sie eine separate Stoppliste für verschiedene Arten von Tweets zur Verfügung, damit ich mich nicht mit der ursprünglichen nltk-Sperrliste anlegen muss. – Harris

2

Mit Rat von mquantin habe ich meinen Code so modifiziert, dass Tweets einzeln als Satz bereinigt werden. Hier ist meine Amateur-Versuch mit einer Probe tweet, dass ich glaube, deckt die meisten Szenarien (Lassen Sie mich wissen, wenn Sie irgendwelche anderen Fällen auftreten, die eine saubere verdienen nach oben):

import string 
import re 
from nltk.corpus import stopwords 
from nltk.tokenize import TweetTokenizer 


cache_english_stopwords=stopwords.words('english') 



def tweet_clean(tweet): 
    # Remove tickers 
    sent_no_tickers=re.sub(r'\$\w*','',tweet) 
    print('No tickers:') 
    print(sent_no_tickers) 
    tw_tknzr=TweetTokenizer(strip_handles=True, reduce_len=True) 
    temp_tw_list = tw_tknzr.tokenize(sent_no_tickers) 
    print('Temp_list:') 
    print(temp_tw_list) 
    # Remove stopwords 
    list_no_stopwords=[i for i in temp_tw_list if i.lower() not in  cache_english_stopwords] 
    print('No Stopwords:') 
    print(list_no_stopwords) 
    # Remove hyperlinks 
    list_no_hyperlinks=[re.sub(r'https?:\/\/.*\/\w*','',i) for i in list_no_stopwords] 
    print('No hyperlinks:') 
    print(list_no_hyperlinks) 
    # Remove hashtags 
    list_no_hashtags=[re.sub(r'#', '', i) for i in list_no_hyperlinks] 
    print('No hashtags:') 
    print(list_no_hashtags) 
    # Remove Punctuation and split 's, 't, 've with a space for filter 
    list_no_punctuation=[re.sub(r'['+string.punctuation+']+', ' ', i) for i in list_no_hashtags] 
    print('No punctuation:') 
    print(list_no_punctuation) 
    # Remove multiple whitespace 
    new_sent = ' '.join(list_no_punctuation) 
    # Remove any words with 2 or fewer letters 
    filtered_list = tw_tknzr.tokenize(new_sent) 
    list_filtered = [re.sub(r'^\w\w?$', '', i) for i in filtered_list] 
    print('Clean list of words:') 
    print(list_filtered) 
    filtered_sent =' '.join(list_filtered) 
    clean_sent=re.sub(r'\s\s+', ' ', filtered_sent) 
    #Remove any whitespace at the front of the sentence 
    clean_sent=clean_sent.lstrip(' ') 
    print('Clean sentence:') 
    print(clean_sent) 

s0=' RT @Amila #Test\nTom\'s newly listed Co. &amp; Mary\'s unlisted  Group to supply tech for nlTK.\nh.. $TSLA $AAPL https:// t.co/x34afsfQsh' 
tweet_clean(s0) 
+0

Ändern Sie 'cache_english_stopwords' in einen Satz. Es wird Ihren Code um einen unglaublichen Faktor beschleunigen. – alexis

+0

Wie lese ich in einer Datei, die mehrere Zeilen von Tweets, project3.txt oder .json-Datei enthält – Silas