如何在熊猫中进行复杂的数据清理

时间:2017-04-13 03:02:35

标签: python pandas dataframe

例如,我有一个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)处理不合理的价值。在第2行,杰克的英语得到110超过最大值100.我想将他的得分设置为所有学生英语成绩的平均值。 3)处理Nan值。汤姆的数学成绩是南。我想改为所有学生的数学成绩的平均值。

我可以分别做每一项要求。但我不知道如何做到这三个要求。谢谢!

3 个答案:

答案 0 :(得分:2)

计划

  • 我删除重复项以开始。
  • 使用mask制作得分>比100 null
  • 过滤新数据框并按平均值
  • 分组
  • map表示并使用它来填充空值
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

答案 1 :(得分: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

NaN的{​​{3}}备用解决方案:

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 :(得分: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
相关问题