2017-09-04 32 views
0

我有這樣的數據框,其元素我想要轉換爲那些字符串或列表的集合,並用空集替換那些是無。使用掩碼和錯誤/不兼容的數據框中的類型轉換

id super_graph sub_graph 
GO1 GO1 ['GO4', 'GO5', 'GO6', 'GO7', 'GO8', 'GO9'] GO9 
GO2 GO2 ['GO4', 'GO5', 'GO6', 'GO7', 'GO8', 'GO9'] GO11 
GO3 GO3 ['GO1', 'GO5', 'GO6', 'GO7', 'GO8', 'GO9'] GO12 
GO4 GO4 ['GO1', 'GO6', 'GO7'] 
GO5 GO5 ['GO5'] 
GO6 GO6 ['GO1', 'GO5', 'GO7', 'GO3', 'GO9'] 
GO7 GO7 ['GO2', 'GO5', 'GO6', 'GO7', 'GO8', 'GO10', 'GO11', 'GO12'] 
GO8 GO8 ['GO2', 'GO3', 'GO4', 'GO5', 'GO6', 'GO7', 'GO8', 'GO9']  
GO9 GO9  

我設法在兩個步驟中做到這一點;在列表轉換的字符串,然後使用它們轉換這些列表的步驟:

initial_frame = count_frame.loc[:,['id', "super_graph", "sub_graph"]]#THE FRAME WHOSE EXAMPLE YOU HAVE ABOVE 
initial_frame_mask = ~initial_frame.applymap(lambda cell: isinstance(cell, list)| (cell is None)) 

list_frame = initial_frame.mask(initial_frame_mask,initial_frame.applymap(lambda l: [l])) 
list_frame2 = list_frame.applymap(lambda l: set(l) if l is not None else {}) 

的訣竅是這裏使用[]列表構造(也許我不應該用這個詞具有的語言非常特殊的意義但我找不到更好的),而不是list_frame創建的list(l),因爲它們的行爲不同,[]會採用一個字符串,list()會將字符串序列分解爲它們的部分。

然後,我使用set()方法和條件表達式轉換這些列表以避免包含無(最終目標是爲列的每一行添加所有三個列表(也許我可以使用更好的方法,不要知道,但無論如何,我要回答到的關注對象的問題,個人造就)

其實我打算做這一步,使用的代碼如下:

initial_frame = count_frame.loc[:,['id', "super_graph", "sub_graph"]] 
initial_frame_mask = ~initial_frame.applymap(lambda cell: isinstance(cell, list)) 

list_frame = initial_frame.mask(initial_frame_mask,initial_frame.applymap(lambda l: {l}) if l is not None else {}) 

但是Python不會讓我這樣做:) 實際上,set()方法接受列表和字符串,其行爲類似於list()方法。因此,我打算使用{}來做到這一點,但它不起作用;拋出這個異常:

list_frame = initial_frame.mask(initial_frame_mask,initial_frame.applymap(lambda l: {l} if l is not None else {})) 

TypeError: ("unhashable type: 'list'", 'occurred at index super_graph') 

正是因爲這樣做

In [354]: l=[1,2] 
In [355]: {l} 
Traceback (most recent call last): 

    File "<ipython-input-355-37b01148d270>", line 1, in <module> 
    {l} 

TypeError: unhashable type: 'list' 

所以我相信面具方法選擇整體上進行矢量化操作之後的數據,但這樣,這會觸發這個錯誤,我實際上不應該看到,因爲我的initial_frame_mask很適合避免不方便的值。

id super_graph sub_graph 
GO1 True False True 
GO2 True False True 
GO3 True False True 
GO4 True False False 
GO5 True False False 
GO6 True False False 
GO7 True False False 
GO8 True False False 
GO9 True False False 

所以我想知道我可以在一個步驟做到這一點(可能使用了類似的功能,即不表現得像面具,但要避免開始與壞的值,或用另一種方式來轉換這個)。 我也想知道爲什麼list和[]行爲如此不同,我沒有看到任何Python文檔解釋這是有意的,同樣也是set()和{}。 提前致謝。

Quicknote:確實:list_frame2 = list_frame.applymap(拉姆達升:設定(L)如果L不無其他{})將不會工作,因爲它輸出

id super_graph sub_graph 
GO1 {GO1}  {nan}  {GO9} 
GO2 {GO2}  {nan} {GO11} 
GO3 {GO3}  {nan} {GO12} 
GO4 {GO4}  {nan}  {nan} 
GO5 {GO5}  {nan}  {nan} 
GO6 {GO6}  {nan}  {nan} 
GO7 {GO7}  {nan}  {nan} 
GO8 {GO8}  {nan}  {nan} 
GO9 {GO9}  {nan}  {nan} 

編輯:數據幀生成器(但我認爲這是從剪貼板中做到這一點的命令,這就是爲什麼我起初並不包括它,對不起;

count_frame = pd.DataFrame([["GO2","GO3","GO4","GO5","GO6","GO7","GO8","GO9"],\ 
[["GO4", "GO5","GO6","GO7","GO8","GO9"], 
["GO4", "GO5","GO6","GO7","GO8","GO9"], 
["GO1", "GO5","GO6","GO7","GO8","GO9"], 
["GO1", "GO6","GO7"], 
["GO5"] 
["GO1", "GO5","GO7","GO3","GO9"], 
["GO2", "GO5","GO6","GO7","GO8","GO10","GO11", "GO12"], 
["GO2", "GO3","GO4","GO5","GO6","GO7","GO8","GO9"], 
],\ 
["GO9","GO11","GO12"]], index = ['id','super_graph','sub_graph'], columns=["GO1","GO2","GO3","GO4","GO5","GO6","GO7","GO8","GO9","]).T 
+1

你能提供生成輸入的方法數據幀?目前還不清楚「dtypes」是什麼。 – IanS

+1

您是否嘗試過使用「{* l}」而不是「{l}」? – Uvar

+0

這將是一個很好的電話,但它會打破字符串。無論如何,我最後繼續清單,然後總結這些然後轉換這些集(我有一個無條件的無條件使用,如果None用{}取代無與字典,但無論如何寫入如果None然後set()doesn'不會改變任何東西和總和不能很好地與設置...) –

回答

1

可以跳過掩模步驟,直接進入映射

其實。 ,通過介紹以下內容,我覺得你創造了自己的問題。

initial_frame_mask = ~initial_frame.applymap(lambda cell: isinstance(cell, list)) 

這引入了一個面膜哪個是假的所有列表,因此對於相當多的super_graph所有元素,但會發生什麼其他元素是不完全透明的。

要實現你彷彿想,在一行代碼:

initial_frame = count_frame.loc[:,['id', "super_graph", "sub_graph"]] 
initial_frame.applymap(lambda l: {*l} if isinstance(l, list) else {l}) 

編輯:如果您不希望爲「無」出現在你的數據框,你可以先用替換這些值一個方便的。

initial_frame.fillna('').applymap(lambda l: {*l} if isinstance(l, list) else {l}) 

EDIT2:哈克解決方案,讓名單與獨特的項目(也可以做到這一點作爲oneliner,但估計這已經是令人費解就夠了):

initial_frame['ss'] = initial_frame.fillna('').applymap(lambda l: [*l] if isinstance(l, list) else []).values.sum(axis=1) 
initial_frame['ss'].apply(lambda x: list(filter(None,{*x}))) 
+0

問題是,我不想包括無套,因爲這將是繁瑣的消除它們,但我想我可以實現這與initial_frame.applymap (lambda l:{* l}如果l不是其他情況無如果l isinstance(l,list)else {l})。加上無論如何,我意識到我無法總結與列表(working_series = list_frame.sum(axis = 1))的方式集合,所以我在列表中完全做到這一點,然後使用working_series.map(set)(否則我有一套只有浮動的套數,奇怪的是,對於列表來說都沒問題)。無論如何,我會接受你的答案,因爲你確實回答了問題 –

+1

如果你想擺脫Nones,你可以做'initial_frame.fillna('')'。至於軸1上的總和,這可能會產生可怕的結果,如'{'GO3'}'等等或者只是float64s'0'。 – Uvar

+0

是的,實際上我在None部分弄錯了,我想用列表填充,但這是不可能的,所以我試圖在替換它們之後替換它們(字符串替換沒有發生在我身上,我對此很愚蠢,因爲我無論如何替換字符串)。對於求和部分,我並沒有比求和列表更好的調用,因爲使用set不起作用,並且我想要靈活的地方,我不需要指定索引或標籤或循環等等。所以我想用列表來看,應該沒問題?每次不打開包裝可能會比使用面罩的效率更低效? –

相關問題