2016-07-24 138 views
3

我試圖從tweet文本中篩選所有#關鍵字。我使用str.extractall()來提取關鍵字#的所有關鍵字。 這是我第一次使用熊貓過濾來自tweetText的關鍵字。輸入,代碼,預期輸出和錯誤如下。Pandas給出的錯誤來自str.extractall('#')

輸入:

userID,tweetText 
01, home #sweet home 
01, #happy #life 
02, #world peace 
03, #all are one 
04, world tour 

等等...總的數據文件是GB大小刮鳴叫與其他幾列。但我只對兩列感興趣。

代碼:

import re 
import pandas as pd 

data = pd.read_csv('Text.csv', index_col=0, header=None, names=['userID', 'tweetText']) 

fout = data['tweetText'].str.extractall('#') 

print fout 

預期輸出:

userID,tweetText 
01,#sweet 
01,#happy 
01,#life 
02,#world 
03,#all 

錯誤:

Traceback (most recent call last): 
    File "keyword_split.py", line 7, in <module> 
    fout = data['tweetText'].str.extractall('#') 
    File "/usr/local/lib/python2.7/dist-packages/pandas/core/strings.py", line 1621, in extractall 
    return str_extractall(self._orig, pat, flags=flags) 
    File "/usr/local/lib/python2.7/dist-packages/pandas/core/strings.py", line 694, in str_extractall 
    raise ValueError("pattern contains no capture groups") 
ValueError: pattern contains no capture groups 

在此先感謝您的幫助。過濾關鍵字的最簡單方法是什麼?

輸出更新:

在使用時只有此輸出像上面 s.name = "tweetText" data_1 = data[~data['tweetText'].isnull()]

在這種情況下輸出具有空[]和用戶ID在仍然列,併爲那些具有關鍵字具有的陣列關鍵字而不是列表形式。

當僅使用此輸出我們什麼需要的,但與NAN

s.name = "tweetText" 
data_2 = data_1.drop('tweetText', axis=1).join(s) 

輸出這裏是正確的格式,但那些沒有關鍵字還沒有考慮,具有NAN

如果可能的話,我們得到忽略這樣的用戶ID,並且根本不顯示在輸出中。在下一階段,我試圖計算關鍵字的頻率,其中NAN或空的[]也將被計數,並且該頻率可能危及未來遠期的分類。

enter image description here

回答

3

如果你是不是太依賴於使用extractall,你可以嘗試以下操作來獲得最終輸出:

from io import StringIO 
import pandas as pd 
import re 


data_text = """userID,tweetText 
01, home #sweet home 
01, #happy #life 
02, #world peace 
03, #all are one 
""" 

data = pd.read_csv(StringIO(data_text),header=0) 

data['tweetText'] = data.tweetText.apply(lambda x: re.findall('#(?=\w+)\w+',x)) 
s = data.apply(lambda x: pd.Series(x['tweetText']),axis=1).stack().reset_index(level=1, drop=True) 
s.name = "tweetText" 
data = data.drop('tweetText', axis=1).join(s) 

    userID tweetText 
0  1 #sweet 
1  1 #happy 
1  1  #life 
2  2 #world 
3  3  #all 
4  4  NaN 

你降textTweet列返回Nan的行通過執行以下操作:

data = data[~data['tweetText'].isnull()] 

這應返回:

userID tweetText 
0  1 #sweet 
1  1 #happy 
1  1  #life 
2  2 #world 
3  3  #all 

我希望這有助於。

+0

這可以創造奇蹟!非常感謝你......除了沒有關鍵字的'userID'的'Nan'外。這是我一直在努力的。 –

+1

不客氣!如果'Nan'的表現不夠好,你可以使用'fillna'來填充你選擇的'Nan'。 – Abdou

+0

不需要包含那些不包含'#關鍵字'的文件,但是是否可以在tweetText中添加其他關鍵字? –

2

extractall功能需要與捕獲組作爲第一個參數,已爲其提供#一個正則表達式模式

可能的參數可能是(#\S+)。大括號表示一個捕獲組,換言之,函數需要從每個字符串中提取哪些內容。

例子:

data="""01, home #sweet home 
01, #happy #life 
02, #world peace 
03, #all are one 
""" 

import pandas as pd 
from io import StringIO 

df = pd.read_csv(StringIO(data), 
       header=None, 
       names=['col1', 'col2'], 
       index_col=0) 

df['col2'].str.extractall('(#\S+)') 

錯誤ValueError: pattern contains no capture groups並不與上面的代碼再出現(這意味着在討論的問題解決),但這種打在大熊貓的當前版本(我的錯誤」使用'0.18.1')。

返回的錯誤是:

AssertionError: 1 columns passed, passed data had 6 columns 

問題描述here

如果你想嘗試df['col2'].str.extractall('#(\S)')(它會給你每個hashtag的第一個字母,你會發現extractall函數工作,只要被捕獲的組只包含一個字符(與問題描述相匹配)。該問題已經結束,應該固定在即將到來的大熊貓發佈

+0

謝謝你的提議。即使更改後,錯誤也是一樣的。可能是任何提取的選項? –

+0

非常感謝你的解釋。幫助很多:)我擁有同一版本的熊貓。 –

+0

@Merlin是的,我測試過,它沒有問題 –

0

試試這個:

由於它過濾了 '#',您應該NAN不存在。

data = pd.read_csv(StringIO(data_text),header=0, index_col=0) 
    data = data["tweetText"].str.split(' ', expand=True).stack().reset_index().rename(columns = {0:"tweetText"}).drop('level_1', 1) 
    data = data[data['tweetText'].str[0] == "#"].reset_index(drop=True) 


    userID tweetText 
0  1 #sweet 
1  1 #happy 
2  1  #life 
3  2 #world 
4  3  #all 

@Abdou方法:

def try1(): 
    data = pd.read_csv(StringIO(data_text),header=0) 
    data['tweetText'] = data.tweetText.apply(lambda x: re.findall('#(?=\w+)\w+',x)) 
    s = data.apply(lambda x: pd.Series(x['tweetText']),axis=1).stack().reset_index(level=1, drop=True) 
    s.name = "tweetText" 
    data = data.drop('tweetText', axis=1).join(s) 
    data = data[~data['tweetText'].isnull()] 

%timeit try1() 
100 loops, best of 3: 7.71 ms per loop 

@Merlin方法

def try2(): 
    data = pd.read_csv(StringIO(data_text),header=0, index_col=0) 
    data = data["tweetText"].str.split(' ', expand=True).stack().reset_index().rename(columns = {'level_0':'userID',0:"tweetText"}).drop('level_1', 1) 
    data = data[data['tweetText'].str[0] == "#"].reset_index(drop=True) 

%timeit try2() 
100 loops, best of 3: 5.36 ms per loop 
+0

謝謝你的簡短解決方案。但是,在輸出中,如果您看到userID中的第一個條目顯示爲「0」,那麼它應該是「1」。 –

+0

我可以請求這個小小的幫助吧http://stackoverflow.com/questions/38524071/parse-user-name-for-extracting-user-location-twitter –

1

大括號中的微積分:

fout = data['tweetText'].str.extractall('(#)') 

代替

fout = data['tweetText'].str.extractall('#') 

希望能工作