20. Pandas的数据清洗-删除NaN
数据清洗(Tidy Data),是对数据进行重新审查和校验的过程,目的在于删除重复信息、纠正存在的错误,并提供数据一致性。
Pandas提供了很多的工具和函数可以对缺失、重复的数据进行相应的数据的处理。
20.1 构造缺失数据
在Pandas的各类数据Series和DataFrame里字段值为NaN的为缺失数据,不代表0而是说没有赋值数据。数据的缺失有很多原因,缺失不是错误、无效,需要对缺失的数据进行必要的技术处理,以便后续的计算、统计。
构造缺失数据的DataFrame
import pandas as pd
import numpy as np
val = np.arange(10, 38).reshape(7, 4)
col = list("abcd")
idx = "cake make fake sake wake lake take".split()
df = pd.DataFrame(val, columns = col, index = idx)
print df
df["e"] = np.nan
df.at["make", "e"] = 100
df.at["wake", "e"] = 300
df.loc["jake"] = np.nan
df.at["jake", "c"] = 200
df["f"] = np.nan
print df
执行结果:
a b c d
cake 10 11 12 13
make 14 15 16 17
fake 18 19 20 21
sake 22 23 24 25
wake 26 27 28 29
lake 30 31 32 33
take 34 35 36 37
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 300 NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
jake NaN NaN 200 NaN NaN NaN
20.2 查看缺失数据
查看缺失数据的情况可以用pandas的isnull函数看看有那些字段上的数据缺失,可以用sum进行统计。也可使用notnull和count函数统计非NaN数据量。
import pandas as pd
import numpy as np
val = np.arange(10, 38).reshape(7, 4)
col = list("abcd")
idx = "cake make fake sake wake lake take".split()
df = pd.DataFrame(val, columns = col, index = idx)
print df
df["e"] = np.nan
df.at["make", "e"] = 100
df.at["wake", "e"] = 300
df.loc["jake"] = np.nan
df.at["jake", "c"] = 200
df["f"] = np.nan
print df
print "which has Nan?\n", df.isnull(),"\n"
print "each column has NaN\n", df.isnull().sum(),"\n"
print "total has NaN\n", df.isnull().sum().sum(),"\n"
print "each column values\n", df.count(),"\n"
print "which column values\n", df.notnull(),"\n"
执行结果如下:
a b c d
cake 10 11 12 13
...
take 34 35 36 37
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 300 NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
jake NaN NaN 200 NaN NaN NaN
which has Nan?
a b c d e f
cake False False False False True True
make False False False False False True
fake False False False False True True
sake False False False False True True
wake False False False False False True
lake False False False False True True
take False False False False True True
jake True True False True True True
each column has NaN
a 1
b 1
c 0
d 1
e 6
f 8
dtype: int64
total has NaN
17
each column values
a 7
b 7
c 8
d 7
e 2
f 0
dtype: int64
which column values
a b c d e f
cake True True True True False False
make True True True True True False
fake True True True True False False
sake True True True True False False
wake True True True True True False
lake True True True True False False
take True True True True False False
jake False False True False False False
20.3 布尔选择删除
删除NaN(主要针对列Series),在pandas里可以使用布尔选择或者dropna函数删除DataFrame的某Series列里的数据,但不会影响DataFrame本身。
import pandas as pd
import numpy as np
val = np.arange(10, 38).reshape(7, 4)
col = list("abcd")
idx = "cake make fake sake wake lake take".split()
df = pd.DataFrame(val, columns = col, index = idx)
df["e"] = np.nan
df.at["make", "e"] = 100
df.at["wake", "e"] = 300
df.loc["jake"] = np.nan
df.at["jake", "c"] = 200
df["f"] = np.nan
print df
print df.e[df.e.notnull()]
print df.e.dropna()
print df
执行结果:
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 300 NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
jake NaN NaN 200 NaN NaN NaN # print df
make 100
wake 300
Name: e, dtype: float64 # print df.e[df.e.notnull()]
make 100
wake 300
Name: e, dtype: float64 # print df.e.dropna()
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 300 NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
jake NaN NaN 200 NaN NaN NaN # print df
20.4 使用dropna函数删除
如果对DataFrame使用了dropna那么行上有NaN的会被删除这行得到结果不直接会影响DataFrame本身。
import pandas as pd
import numpy as np
val = np.arange(10, 38).reshape(7, 4)
col = list("abcd")
idx = "cake make fake sake wake lake take".split()
df = pd.DataFrame(val, columns = col, index = idx)
print df
df["e"] = np.nan
df.at["make", "e"] = 100
print df
print df.dropna()
print df
执行结果:
a b c d
cake 10 11 12 13
make 14 15 16 17
fake 18 19 20 21
sake 22 23 24 25
wake 26 27 28 29
lake 30 31 32 33
take 34 35 36 37# print df
a b c d e
cake 10 11 12 13 NaN
make 14 15 16 17 100
fake 18 19 20 21 NaN
sake 22 23 24 25 NaN
wake 26 27 28 29 NaN
lake 30 31 32 33 NaN
take 34 35 36 37 NaN # print df
a b c d e
make 14 15 16 17 100 # print df.dropna()
a b c d e
cake 10 11 12 13 NaN
make 14 15 16 17 100
fake 18 19 20 21 NaN
sake 22 23 24 25 NaN
wake 26 27 28 29 NaN
lake 30 31 32 33 NaN
take 34 35 36 37 NaN # print df
20.5 行删除NaN
如果仅想删除行里全都是NaN的行,可以在dropna函数里使用how= 'all'参数。
import pandas as pd
import numpy as np
val = np.arange(10, 38).reshape(7, 4)
col = list("abcd")
idx = "cake make fake sake wake lake take".split()
df = pd.DataFrame(val, columns = col, index = idx)
df["e"] = np.nan
df.at["make", "e"] = 100
df["f"] = np.nan
df.loc["gake"] = np.nan
print df
print "del cols is all NaN\n", df.dropna(axis = 'columns', how='all')
print df
print "del rows is all NaN\n", df.dropna(axis = 'rows', how='all')
print df
执行结果:
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 NaN NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
gake NaN NaN NaN NaN NaN NaN
del cols is all NaN
a b c d e
cake 10 11 12 13 NaN
make 14 15 16 17 100
fake 18 19 20 21 NaN
sake 22 23 24 25 NaN
wake 26 27 28 29 NaN
lake 30 31 32 33 NaN
take 34 35 36 37 NaN
gake NaN NaN NaN NaN NaN
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 NaN NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
gake NaN NaN NaN NaN NaN NaN
del rows is all NaN
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 NaN NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 NaN NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
gake NaN NaN NaN NaN NaN NaN
20.6 设定阈值删除
如果想保留含有若干非空值的行或者列可以使用thresh参数。
import pandas as pd
import numpy as np
val = np.arange(10, 38).reshape(7, 4)
col = list("abcd")
idx = "cake make fake sake wake lake take".split()
df = pd.DataFrame(val, columns = col, index = idx)
df["e"] = np.nan
df.at["make", "e"] = 100
df["f"] = np.nan
df.loc["gake"] = np.nan
print df
print df.dropna(axis = 1, thresh = 2)
程序里axis = 1, thresh = 2是说列上至少有两个非NaN的列留下。
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 NaN NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
gake NaN NaN NaN NaN NaN NaN
a b c d
cake 10 11 12 13
make 14 15 16 17
fake 18 19 20 21
sake 22 23 24 25
wake 26 27 28 29
lake 30 31 32 33
take 34 35 36 37
gake NaN NaN NaN NaN
a b c d e f
cake 10 11 12 13 NaN NaN
make 14 15 16 17 100 NaN
fake 18 19 20 21 NaN NaN
sake 22 23 24 25 NaN NaN
wake 26 27 28 29 NaN NaN
lake 30 31 32 33 NaN NaN
take 34 35 36 37 NaN NaN
gake NaN NaN NaN NaN NaN NaN
20.7 影响DataFrame参数
如果想dropna函数想直接影响dataframe本身可以使用参数inplace=True。