上手Pandas,带你玩转数据(4)-- 数据清洗
描述性方法
在讲数据清洗之前,我想先讲一些描述性的方法。不然后面讲清洗的时候会有点突兀。
S.No. | 功能 | 描述 |
---|---|---|
1 | count() | 非空观测值的数量 |
2 | sum() | 值的总和 |
3 | mean() | 价值的意义 |
4 | median() | 价值的中间值 |
5 | mode() | 价值观的模式 |
6 | std() | 价值观的标准差 |
7 | min() | 最小值 |
8 | max() | 最大值 |
9 | abs() | 绝对值 |
10 | prod() | 价值的产物 |
11 | cumsum() | 累计和 |
12 | cumprod() | 累积产品 |
哪个不会用呢?
那来个示例看一下:
df = pd.DataFrame(d)
print(df.std())
- 1
- 2
伪代码,仅供参考。
注:
由于DataFrame是一个异构数据结构。 通用操作不适用于所有功能。
sum(),cumsum() 等函数可以同时处理数字和字符(或)字符串数据元素,而不会出现任何错误。虽然练习中,角色聚合从来不会被普遍使用,但这些功能不会抛出任何异常。
当DataFrame包含字符或字符串数据时 像 abs(),cumprod() 等函数会抛出异常,因为无法执行这些操作。
汇总数据
describe()函数是用来计算有关DataFrame列的统计信息的摘要。
执行这个函数,我们可以获得数据的:
Age Rating
count 12.000000 12.000000
mean 31.833333 3.743333
std 9.232682 0.661628
min 23.000000 2.560000
25% 25.000000 3.230000
50% 29.500000 3.790000
75% 35.500000 4.132500
max 51.000000 4.800000
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
晓得吧,看最左边那一列,其他都不用看了。
该函数给出了平均值,标准差和IQR值。 而且,函数排除字符列,并给出关于数字列的摘要。
这个函数有一个参数要注意一下:include。
看参数的名字应该猜个八九不离十了吧。包含,对,如果我们的列数很多的时候,我又不想查看所有列的描述,那这样不就很麻烦?于是就给了include这个参数让你自己去选。
include默认为“数字”,当然,除了可以自定义以外,系统也提供了以下几个选择:
object - 汇总字符串列
number - 汇总数字列
all - 将所有列汇总在一起(不应将其作为列表值传递)
- 1
- 2
- 3
- 4
- 5
pandas处理文本数据
Pandas提供了一组字符串函数,可以很容易地对字符串数据进行操作。最重要的是,这些函数忽略(或排除)丢失/ NaN值。
S.No | 功能 | 描述 |
---|---|---|
1 | lower() | 将Series / Index中的字符串转换为小写字母。 |
2 | upper() | 将Series / Index中的字符串转换为大写。 |
3 | len() | 计算字符串的长度()。 |
4 | strip() | 帮助从两侧删除Series / index中每个字符串的空格(包括换行符)。 |
5 | split(’ ') | 用给定的模式分割每个字符串。 |
6 | cat(sep=’ ') | 使用给定的分隔符连接序列/索引元素。 |
7 | get_dummies() | 用One-Hot Encoded值返回DataFrame。 |
8 | contains(pattern) | 如果子字符串包含在元素中,则返回每个元素的布尔值True,否则返回False。 |
9 | replace(a,b) | 替换值 一个 与值 b 。 |
10 | repeat(value) | 以指定的次数重复每个元素。 |
11 | count(pattern) | 返回每个元素中的模式出现次数。 |
12 | startswith(pattern) | 如果Series / Index中的元素以模式开始,则返回true。 |
13 | endswith(pattern) | 如果Series / Index中的元素以模式结尾,则返回true。 |
14 | find(pattern) | 返回模式第一次出现的第一个位置。 |
15 | findall(pattern) | 返回模式的所有出现的列表。 |
16 | swapcase | 将箱子更换/更换。 |
17 | islower() | 检查Series / Index中每个字符串中的所有字符是否小写。返回布尔值 |
18 | isupper() | 检查Series / Index中每个字符串中的所有字符是否大写。返回布尔值。 |
19 | isnumeric() | 检查Series / Index中每个字符串中的所有字符是否为数字。返回布尔值。 |
检查缺失值
为了更容易地检测缺失值(以及跨越不同的数组dtype),Pandas提供了 isnull() 和 notnull() 函数,它们也是Series和DataFrame对象的方法(python中用NaN(Not a Number)表示缺失数据):
df = pd.DataFrame([[1,5,8],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
- 1
0 1 2
0 1.0 5.0 8.0
1 2.0 NaN NaN
2 2.0 3.0 NaN
3 NaN NaN NaN
- 1
- 2
- 3
- 4
- 5
判断行列中是否有空数据
axis=0,代表列,axis=1代表行
查看行:df.isnull().any(axis=1)
查看列:df.isnull().any(axis=0)
- 1
- 2
我弄了个按行判断的你们看一下:
0 False
1 True
2 True
3 True
dtype: bool
- 1
- 2
- 3
- 4
- 5
再看一下这个:
查看行:df.notnull().all(axis=1)
查看列:df.notnull().all(axis=0)
- 1
- 2
这个的话,只要有非空数据,就会被判断为True。
以上方法,都可以通过取反符号“~”来进行取反。
print(~df.isnull().any(axis = 1))
- 1
也可以通过loc()方法来进行取值。
比方说我要取出所有非空数据行,可以这样来进行实现:
df = df.loc[~df.isnull().any(axis = 1)]
- 1
0 1 2
0 1.0 5.0 8.0
- 1
- 2
至于这个loc()方法,等会儿会说。
你也可以指定一列来进行空值的判断:
print(df[1].isnull()) # 判断一列的空值
print(df[1].isnull().value_counts()) # 对一列空值数量进行统计
- 1
- 2
清洗、填充缺失值
清理含有缺失值的行/列
相对来说有一个很直接的方法,直接将所有有空值的行、列进行清除:
df = pd.DataFrame([[1,5,8],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.dropna()
print(df)
- 1
- 2
- 3
- 4
- 5
不附加任何的额外条件,只要你那一行里面存在空值,一行清理。
0 1 2
0 1.0 5.0 8.0
- 1
- 2
如果是要按列清理呢?那就加上:
df = pd.DataFrame([[1,5,8],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.dropna(axis=1)
print(df)
- 1
- 2
- 3
- 4
- 5
啊,很遗憾的告诉你,全部被清理了,一点不剩,因为每一列都有空值啊。。。
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3]
- 1
- 2
- 3
在坏值容忍度下删除行/列
好,那你现在跟我说,你觉得一行有那么一两个坏值其实是可以忍受的,那我怎么办?那我不还得给你办嘛:
# 只要有n个值是好的,就留下:
df = pd.DataFrame([[1,5,8],[np.nan,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.dropna(thresh=1) # n
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
0 1 2
0 1.0 5.0 8.0
2 2.0 3.0 NaN
- 1
- 2
- 3
对吧。那这要不是你想要的,那我也没办法了。
删除指定行/列
还有什么,删除指定列?删除指定行?那试试看嘛,摸索一下。
df = pd.DataFrame([[1,5,8],[np.nan,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.drop(labels=1)
print(df)
- 1
- 2
- 3
- 4
- 5
0 1 2
0 1.0 5.0 8.0
2 2.0 3.0 NaN
3 NaN NaN NaN
- 1
- 2
- 3
- 4
呐,我把那第一列删了。
神乎其技!!!
df = pd.DataFrame([[1,5,8],[np.nan,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.drop(columns=2)
print(df)
- 1
- 2
- 3
- 4
- 5
不好意思,上面删的是一行,这里才是删一列。。。
0 1
0 1.0 5.0
1 NaN NaN
2 2.0 3.0
3 NaN NaN
- 1
- 2
- 3
- 4
- 5
填充缺失值
现在让我们把数据集换回去。
然后填充一下缺失值:
df = pd.DataFrame([[1,5,np.nan],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.fillna(value=0) # 以指定值对缺失值进行填补
print(df)
- 1
- 2
- 3
- 4
- 5
0 1 2
0 1.0 5.0 0.0
1 2.0 0.0 0.0
2 2.0 3.0 0.0
3 0.0 0.0 0.0
- 1
- 2
- 3
- 4
- 5
用某一列的平均值对某一列进行填充:
df = pd.DataFrame([[1,5,np.nan],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
print(df)
df[1] = df.fillna(df[1].mean())
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
0 1 2
0 1.0 5.0 NaN
1 2.0 NaN NaN
2 2.0 3.0 NaN
3 NaN NaN NaN 0 1 2
0 1.0 5.0 1.0
1 2.0 NaN 2.0
2 2.0 3.0 2.0
3 NaN NaN NaN
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
要不你试试第二列?
呐,不指定列试试看:
df = pd.DataFrame([[1,5,np.nan],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
print(df)
df = df.fillna(df.mean())
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
自上而下填充:
df = df.fillna(method='ffill')
print(df)
- 1
- 2
- 3
0 1 2
0 1.0 5.0 NaN
1 2.0 NaN NaN
2 2.0 3.0 NaN
3 NaN NaN NaN 0 1 2
0 1.0 5.0 NaN
1 2.0 5.0 NaN
2 2.0 3.0 NaN
3 2.0 3.0 NaN
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
有自上而下就有自下而上了:
df = df.fillna(method='bfill')
print(df)
- 1
- 2
- 3
0 1 2
0 1.0 5.0 NaN
1 2.0 NaN NaN
2 2.0 3.0 NaN
3 NaN NaN NaN 0 1 2
0 1.0 5.0 NaN
1 2.0 3.0 NaN
2 2.0 3.0 NaN
3 NaN NaN NaN
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
消除数据中的空格
# 创建含有空格的数据
dict1 = {"name": ["小红", "小明", "小张"], "age": [16, 17, 18], "city": ["北京 ", "杭州", " 上海 "]}
df2 = pd.DataFrame(dict1, columns=["name", "age", "city"])
print(df2)
# 清除空格
df2["city"] = df2["city"].map(str.strip)
print(df2)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
name age city
0 小红 16 北京
1 小明 17 杭州
2 小张 18 上海 name age city
0 小红 16 北京
1 小明 17 杭州
2 小张 18 上海
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
去重
如果你拿到一个数据集,非常大,你感觉里面有不少重复值,想要进行一波去重操作,怎么办?
还有一个drop_duplicates还没看。
换个数据集玩玩吧,一直用那个也累了。
df = pd.DataFrame({'Country':[1,1,2,12,34,23,45,34,23,12,2,3,4,1], 'Income':[1,1,2,10000, 10000, 5000, 5002, 40000, 50000, 8000, 5000,3000,15666,1], 'Age':[1,1,2,50, 43, 34, 40, 25, 25, 45, 32,12,32,1], 'group':[1,1,2,'a','b','s','d','f','g','h','a','d','a',1]})
- 1
- 2
- 3
- 4
- 5
- 6
Country Income Age group
0 1 1 1 1
1 1 1 1 1
2 2 2 2 2
3 12 10000 50 a
4 34 10000 43 b
5 23 5000 34 s
6 45 5002 40 d
7 34 40000 25 f
8 23 50000 25 g
9 12 8000 45 h
10 2 5000 32 a
11 3 3000 12 d
12 4 15666 32 a
13 1 1 1 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
直接上手去重:
df.drop_duplicates(inplace=True) #inplace=True 对原表进行修改
- 1
Country Income Age group
0 1 1 1 1
2 2 2 2 2
3 12 10000 50 a
4 34 10000 43 b
5 23 5000 34 s
6 45 5002 40 d
7 34 40000 25 f
8 23 50000 25 g
9 12 8000 45 h
10 2 5000 32 a
11 3 3000 12 d
12 4 15666 32 a
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
少了一列啊。
大家看数据表中的索引,在我们使用drop_duplicates删除重复行时,重复行相对应的索引值也是被默认删除掉的,也就是说,索引值已经发生了变化。
那我们该如何解决这个问题呢?
df.drop_duplicates(inplace=True)
df = df.reset_index(drop=True)
print(df)
- 1
- 2
- 3
Country Income Age group
0 1 1 1 1
1 2 2 2 2
2 12 10000 50 a
3 34 10000 43 b
4 23 5000 34 s
5 45 5002 40 d
6 34 40000 25 f
7 23 50000 25 g
8 12 8000 45 h
9 2 5000 32 a
10 3 3000 12 d
11 4 15666 32 a
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
如果要指定保留的重复行(默认是第一行),可以使用keep参数:一般没什么给你选的,要么就first,要么就last。
对指定的数据列进行去重:
df.drop_duplicates(inplace=True,subset = ['Age'],keep='last')
df = df.reset_index(drop=True)
print(df)
- 1
- 2
- 3
- 4
- 5
0 2 2 2 2
1 12 10000 50 a
2 34 10000 43 b
3 23 5000 34 s
4 45 5002 40 d
5 23 50000 25 g
6 12 8000 45 h
7 3 3000 12 d
8 4 15666 32 a
9 1 1 1 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如果要多几行呢?
这操作叫什么?思考一下数据库中的主键。
df.drop_duplicates(inplace=True,subset = ['Age','group'],keep='last')
df = df.reset_index(drop=True)
print(df)
- 1
- 2
- 3
- 4
- 5
Country Income Age group
0 2 2 2 2
1 12 10000 50 a
2 34 10000 43 b
3 23 5000 34 s
4 45 5002 40 d
5 34 40000 25 f
6 23 50000 25 g
7 12 8000 45 h
8 3 3000 12 d
9 4 15666 32 a
10 1 1 1 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
如果不出意外,这篇就到这里啦,see you!!!
文章来源: blog.csdn.net,作者:看,未来,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/qq_43762191/article/details/115496766
- 点赞
- 收藏
- 关注作者
评论(0)