2017-04-13 34 views
2

例如,我有一個DataFrame如下。如何在熊貓中進行復雜的數據清理

lineNum  id   name   Cname   score 
    1   001  Jack    Math   99 
    2   002  Jack    English  110 
    3   003  Jack    Chinese  90 
    4   003  Jack    Chinese  90 
    5   004  Tom    Math   Nan 
    6   005  Tom    English  75 
    7   006  Tom    Chinese  85 

正如你所看到的,我想爲這些數據清理數據。 1)刪除第3行和第4行的重複值。 2)處理不合理的值。在第二行,傑克的英語得到110,超過了最大值100.我想將他的分數設置爲所有學生英語得分的平均值。 3)處理南的價值。湯姆的數學成績是南。我想改變爲所有學生數學成績的平均值。

我可以分別做各種要求。但我不知道如何完成這三項要求。謝謝!

+0

你爲什麼不先執行每個需求1,如先刪除重複項,然後對所有null和out-of-bound值,用平均值 –

+0

替換,您可以使用Dataframe.drop_duplicate(),然後去除110分很容易,因爲你知道max是100,然後使用'Dataframe.fillna()'作爲nan值 –

回答

0

如果數據不是太大,你應該考慮`.apply(func)'。

import pandas as pd 

df = pd.read_table('sample.txt', delimiter='\s+', na_values='Nan') # Your sample data 
df = df.set_index('lineNum').drop_duplicates() 

def deal_with(x): 
    if (x['score'] > 100.) or (pd.isnull(x['score'])): 
     df_ = df[df['id'] != x['id']] 
     x['score'] = df_.loc[df_['Cname'] == x['Cname'], 'score'].mean() 

    return x 

print(df.apply(deal_with, axis=1)) 

     id name Cname score 
lineNum       
1   1 Jack  Math 99.0 
2   2 Jack English 75.0 
3   3 Jack Chinese 90.0 
5   4 Tom  Math 99.0 
6   5 Tom English 75.0 
7   6 Tom Chinese 85.0 
1

您可以使用:

cols = ['id','name','Cname','score'] 
#remove duplicates by columns 
df = df.drop_duplicates(subset=cols) 
#replace values > 100 to NaN 
df.loc[df['score'] > 100, 'score'] = np.nan 
#replace NaN by mean for all students by subject 
df['score'] = df.groupby('Cname')['score'].transform(lambda x: x.fillna(x.mean())) 
print (df) 
    lineNum id name Cname score 
0  1 1 Jack  Math 99.0 
1  2 2 Jack English 75.0 
2  3 3 Jack Chinese 90.0 
4  5 4 Tom  Math 99.0 
5  6 5 Tom English 75.0 
6  7 6 Tom Chinese 85.0 

mask替代解決方案爲NaN

cols = ['id','name','Cname','score'] 
df = df.drop_duplicates(subset=cols) 
df['score'] = df['score'].mask(df['score'] > 100) 

df['score'] = df.groupby('Cname')['score'].apply(lambda x: x.fillna(x.mean())) 
print (df) 
    lineNum id name Cname score 
0  1 1 Jack  Math 99.0 
1  2 2 Jack English 75.0 
2  3 3 Jack Chinese 90.0 
4  5 4 Tom  Math 99.0 
5  6 5 Tom English 75.0 
6  7 6 Tom Chinese 85.0 
2

計劃

  • 我放棄重複開始。
  • 使用mask均值爲
  • 地圖的手段,使分數> 100餘空
  • 過濾器新的數據幀和group by,並用它來填補空

d = df.drop_duplicates(['id', 'name', 'Cname']) 

s0 = d.score 
s1 = s0.mask(s > 100) 
m = s1.mask(s1 > 100).notnull() 

d.assign(score=s1.fillna(d.Cname.map(d[m].groupby('Cname').score.mean()))) 

    lineNum id name Cname score 
0  1 1 Jack  Math 99.0 
1  2 2 Jack English 110.0 
2  3 3 Jack Chinese 90.0 
4  5 4 Tom  Math 99.0 
5  6 5 Tom English 75.0 
6  7 6 Tom Chinese 85.0