2017-09-26 17 views
0

我有一個數據框,包含NaN,我希望groupby和基於兩列進行排序。 NaN不應該位於底部或頂部,而應按非楠列進行排序。嵌套排序,處理NaN - 未觸摸或根據非Nan列排序

Name Upper Lower 
0 A 50.0 45.0 
1 B NaN 2.0 
2 A 30.0 NaN 
3 B 35.0 4.0 
4 A 20.0 15.0 
5 A NaN 30.0 

df.groupby('Name').apply(lambda x: x.sort_values(['Lower','Upper'], ascending=False)) 

     Name Upper Lower 
Name      
A 0 A 50.0 45.0 
    5 A NaN 30.0 
    4 A 20.0 15.0 
    2 A 30.0 NaN 
B 3 B 35.0 4.0 
    1 B NaN 2.0 

我想要的是第2和第4行切換位置。

 Name Upper Lower 
Name      
A 0 A 50.0 45.0 
    5 A NaN 30.0 
    2 A 30.0 NaN 
    4 A 20.0 15.0 
B 3 B 35.0 4.0 
    1 B NaN 2.0 

所以我想要排序'下',但如果它是南然後'上',他們永遠都不會是一行的南。

錯誤pydata#3917會給我我想要的功能。 https://github.com/pandas-dev/pandas/issues/3917

回答

0

我其實認爲你鏈接到的bug與這個用例稍有不同,並且已經得到了有效的修復。

對於你的情況,你可以使用這個技巧:

df['new_column'] = df['Lower'] 
df.ix[pd.isnull(df['new_column']), 'new_column'] = df['Upper'] 
df.ix[pd.notnull(df['Lower']), 'rank'] = df.ix[pd.notnull(df['Lower']), 'Lower'].rank(ascending=False) 
df.ix[pd.isnull(df['rank']) & pd.notnull(df['Upper']), 'rank'] = df.ix[pd.notnull(df['Upper']), 'Upper'].rank(ascending=False) 
df['new_column'] = 1/df['new_column'] 
df.sort_values(['rank', 'new_column'], ascending=True) 

基本上,使新的一列從較低的值。如果Lower缺失,則從Upper獲取值。同樣,將所有的價值排列在較低和較高的位置,並使用相同的邏輯組合等級。然後按排名排序,如果排名與新列相同。

+0

感謝您的回覆@amanbirs!我可能誤解了這個錯誤。不過,這種精神也不會爲我做。即如果第2行是[A,49,Nan](而不是[A,30,Nan]),我會希望它在排序時位於第0行以下,而不是像本解決方案那樣高於第0行。雖然正確的解決方案可能不會遠離這種攻擊。 – maypay

+0

@maypay沒問題。看看我編輯的解決方案。如果我已經正確理解你的問題,這應該工作。 – amanbirs

+0

好吧,做了很多的編輯,這應該工作。雖然這是一個更復雜的解決方案。 – amanbirs