2017-05-09 145 views
4

我正在嘗試拼合行並保留我想要的行的信息。熊貓:基於條件壓平柱?

我有什麼:

id var1 var2 var3 
1  Y  N Y 
1  N   Y 
2  Y   N 
2  N  Y N 
2  Y  N Y 

我想什麼:

id var1 var2 var3 
1  Y  N Y 
2  Y  Y Y 

從本質上講,它會檢查是否有一個Y/N始終以一個Y. 優先也有比var1,var2,var3更多的列;所以我想要更通用的東西,所以我也可以應用到其他列。

+0

聽起來像是你想有一個邏輯OR。 – erip

回答

3

您可以使用replace + groupby + GroupBy.max + replace + reset_index

df1 = df.replace({'Y':1,'N':0, np.nan:-1}) 
     .groupby('id') 
     .max() 
     .replace({1:'Y', 0:'N',-1:np.nan}) 
     .reset_index() 
print (df1) 

    id var1 var2 var3 
0 1 Y N Y 
1 2 Y Y Y 

編輯:

df = pd.DataFrame({ 
'id': [1, 1, 2, 2, 3, 3], 
'var2': ['N', 'N', 'N', 'Y', 'N', np.nan], 
'var1': ['Y', 'Y', 'Y', 'N', 'Y', np.nan], 
'var3': [np.nan, np.nan, np.nan, 'N', np.nan, 'Y'] 
}) 

print (df) 
    id var1 var2 var3 
0 1 Y N NaN 
1 1 Y N NaN 
2 2 Y N NaN 
3 2 N Y N 
4 3 Y N NaN 
5 3 NaN NaN Y 

您可以動態創建另一個dict

#check all unique values without column id 
print (df.set_index('id').stack(dropna=False).unique()) 
['Y' 'N' nan] 

#create dict for first replace 
d = {'Y':1,'N':0, np.nan:-1} 
#swap keys, values in dict for another replace 
d1 = {v: k for k, v in d.items()} 

df1 = df.replace(d).groupby('id').max().replace(d1).reset_index() 
print (df1) 
    id var1 var2 var3 
0 1 Y N NaN 
1 2 Y Y N 
2 3 Y N Y 

EDIT1:

解決方案如果只YNvar1NaN - varN列:

varNAN = 'A' 
print (df.fillna(varNAN).groupby('id').max().replace({varNAN:np.nan}).reset_index()) 
    id var1 var2 var3 
0 1 Y N NaN 
1 2 Y Y N 
2 3 Y N Y 
+0

@erip - 你是對的,所以回答是編輯的。 – jezrael

+0

好編輯 - +1 – erip

+0

@erip - 謝謝。 – jezrael

6

讓我們來試試,你可以使用groupbysum表現得像一個OR,因此 「給Ÿ優先」:

df1 = df.replace({'Y':True,'N':False}) 

df_out = (df1.groupby('id').sum(skipna=False) 
     .astype(bool) 
     .replace({True:'Y',False:'N'}) 
     .reset_index()) 

print(df_out) 

輸出:

id var1 var2 var3 
0 1 Y N Y 
1 2 Y Y Y 
1

如果數據框中只有'Y','N'和NAN,這是一個更簡單的方法。

設置

df = pd.DataFrame({'id': {0: 1, 1: 1, 2: 2, 3: 2, 4: 2}, 
'var1': {0: 'Y', 1: 'N', 2: 'Y', 3: 'N', 4: 'Y'}, 
'var2': {0: 'N', 1: np.nan, 2: np.nan, 3: 'Y', 4: 'N'}, 
'var3': {0: 'Y', 1: 'Y', 2: 'N', 3: 'N', 4: 'Y'}}) 

Out[45]: 
    id var1 var2 var3 
0 1 Y N Y 
1 1 N NaN Y 
2 2 Y NaN N 
3 2 N Y N 
4 2 Y N Y 

解決方案

#Fill na with 'A' and get the max (Y>N>A) from each column. 
df.fillna('A').groupby('id').max().reset_index() 
Out[46]: 
    var1 var2 var3 
id    
1  Y N Y 
2  Y Y Y