飞道的博客

上手Pandas,带你玩转数据(4)-- 数据清洗

270人阅读  评论(0)

描述性方法

在讲数据清洗之前,我想先讲一些描述性的方法。不然后面讲清洗的时候会有点突兀。

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())

伪代码,仅供参考。

注:

由于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

晓得吧,看最左边那一列,其他都不用看了。

该函数给出了平均值,标准差和IQR值。 而且,函数排除字符列,并给出关于数字列的摘要。

这个函数有一个参数要注意一下:include。
看参数的名字应该猜个八九不离十了吧。包含,对,如果我们的列数很多的时候,我又不想查看所有列的描述,那这样不就很麻烦?于是就给了include这个参数让你自己去选。

include默认为“数字”,当然,除了可以自定义以外,系统也提供了以下几个选择:


object - 汇总字符串列
number - 汇总数字列
all - 将所有列汇总在一起(不应将其作为列表值传递)


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]])
     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

判断行列中是否有空数据

axis=0,代表列,axis=1代表行

查看行:df.isnull().any(axis=1)  
查看列:df.isnull().any(axis=0)

我弄了个按行判断的你们看一下:

0    False
1     True
2     True
3     True
dtype: bool

再看一下这个:

查看行:df.notnull().all(axis=1)
查看列:df.notnull().all(axis=0)

这个的话,只要有非空数据,就会被判断为True。


以上方法,都可以通过取反符号“~”来进行取反。

print(~df.isnull().any(axis = 1))

也可以通过loc()方法来进行取值。

比方说我要取出所有非空数据行,可以这样来进行实现:

df = df.loc[~df.isnull().any(axis = 1)]
     0    1    2
0  1.0  5.0  8.0

至于这个loc()方法,等会儿会说。


你也可以指定一列来进行空值的判断:

print(df[1].isnull())	# 判断一列的空值
print(df[1].isnull().value_counts())	# 对一列空值数量进行统计

清洗、填充缺失值

清理含有缺失值的行/列

相对来说有一个很直接的方法,直接将所有有空值的行、列进行清除:

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)

不附加任何的额外条件,只要你那一行里面存在空值,一行清理。

     0    1    2
0  1.0  5.0  8.0

如果是要按列清理呢?那就加上:

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)

啊,很遗憾的告诉你,全部被清理了,一点不剩,因为每一列都有空值啊。。。

Empty DataFrame
Columns: []
Index: [0, 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)
     0    1    2
0  1.0  5.0  8.0
2  2.0  3.0  NaN

对吧。那这要不是你想要的,那我也没办法了。


删除指定行/列

还有什么,删除指定列?删除指定行?那试试看嘛,摸索一下。

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)
     0    1    2
0  1.0  5.0  8.0
2  2.0  3.0  NaN
3  NaN  NaN  NaN

呐,我把那第一列删了。

神乎其技!!!

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)

不好意思,上面删的是一行,这里才是删一列。。。

     0    1
0  1.0  5.0
1  NaN  NaN
2  2.0  3.0
3  NaN  NaN

填充缺失值

现在让我们把数据集换回去。

然后填充一下缺失值:

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)
     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

用某一列的平均值对某一列进行填充:

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)
     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

要不你试试第二列?

呐,不指定列试试看:

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)

自上而下填充:

df = df.fillna(method='ffill')

print(df)
     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

有自上而下就有自下而上了:

df = df.fillna(method='bfill')

print(df)
     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

消除数据中的空格

# 创建含有空格的数据
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)
    name  age    city
0   小红   16    北京  
1   小明   17      杭州
2   小张   18    上海  
    
    name  age  city
0   小红   16   北京
1   小明   17   杭州
2   小张   18   上海

去重

如果你拿到一个数据集,非常大,你感觉里面有不少重复值,想要进行一波去重操作,怎么办?

还有一个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]})
 	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

直接上手去重:

df.drop_duplicates(inplace=True)	#inplace=True 对原表进行修改
    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

少了一列啊。

大家看数据表中的索引,在我们使用drop_duplicates删除重复行时,重复行相对应的索引值也是被默认删除掉的,也就是说,索引值已经发生了变化。

那我们该如何解决这个问题呢?

df.drop_duplicates(inplace=True)
df = df.reset_index(drop=True)
print(df)
	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

如果要指定保留的重复行(默认是第一行),可以使用keep参数:一般没什么给你选的,要么就first,要么就last。


对指定的数据列进行去重:

df.drop_duplicates(inplace=True,subset = ['Age'],keep='last')

df = df.reset_index(drop=True)

print(df)
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

如果要多几行呢?
这操作叫什么?思考一下数据库中的主键。

df.drop_duplicates(inplace=True,subset = ['Age','group'],keep='last')

df = df.reset_index(drop=True)

print(df)
    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

如果不出意外,这篇就到这里啦,see you!!!


转载:https://blog.csdn.net/qq_43762191/article/details/115496766
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场