背景
这个并不是书籍里的章节,因为书籍中的 pandas 节奏太快了,基本都是涉及很多中高级的操作,好容易把小伙伴给劝退。我这里先出几期入门的教程,然后再回到书籍里的教程。这几章节作为入门,书籍作为进阶。
数据清理
数据清理意味着修复你的数据集中的坏数据。
坏的数据可能是:
- • 空单元格
- • 格式错误的数据
- • 错误的数据
- • 重复的数据
在本教程中,你将学习如何处理所有这些问题。
我们的数据集
在接下来的章节中,我们将使用这个数据集:
代码语言:javascript复制 Duration Date Pulse Maxpulse Calories
0 60 '2020/12/01' 110 130 409.1
1 60 '2020/12/02' 117 145 479.0
2 60 '2020/12/03' 103 135 340.0
3 45 '2020/12/04' 109 175 282.4
4 45 '2020/12/05' 117 148 406.0
5 60 '2020/12/06' 102 127 300.0
6 60 '2020/12/07' 110 136 374.0
7 450 '2020/12/08' 104 134 253.3
8 30 '2020/12/09' 109 133 195.1
9 60 '2020/12/10' 98 124 269.0
10 60 '2020/12/11' 103 147 329.3
11 60 '2020/12/12' 100 120 250.7
12 60 '2020/12/12' 100 120 250.7
13 60 '2020/12/13' 106 128 345.3
14 60 '2020/12/14' 104 132 379.3
15 60 '2020/12/15' 98 123 275.0
16 60 '2020/12/16' 98 120 215.2
17 60 '2020/12/17' 100 120 300.0
18 45 '2020/12/18' 90 112 NaN
19 60 '2020/12/19' 103 123 323.0
20 45 '2020/12/20' 97 125 243.0
21 60 '2020/12/21' 108 131 364.2
22 45 NaN 100 119 282.0
23 60 '2020/12/23' 130 101 300.0
24 45 '2020/12/24' 105 132 246.0
25 60 '2020/12/25' 102 126 334.5
26 60 2020/12/26 100 120 250.0
27 60 '2020/12/27' 92 118 241.0
28 60 '2020/12/28' 103 132 NaN
29 60 '2020/12/29' 100 132 280.0
30 60 '2020/12/30' 102 129 380.3
31 60 '2020/12/31' 92 115 243.0
该数据集包含一些空单元格(第22行的 "日期",第18行和第28行的 "卡路里")。
该数据集包含错误的格式(第26行的 "日期")。
该数据集包含错误的数据(第7行的 "持续时间")。
该数据集包含重复的数据(第11行和第12行)。
清理空的值
空值
当你分析数据时,空的单元格有可能给你一个错误的结果。
删除行
处理空单元格的一种方法是删除包含空单元格的行。这通常是可以的,因为数据集可能非常大,删除几行不会对结果有很大影响。
代码语言:javascript复制import pandas as pd
df = pd.read_csv('data.csv')
new_df = df.dropna()
print(new_df.to_string())
Note: 默认情况下,
dropna()
方法返回一个新的DataFrame,不会改变原来的。
如果你想改变原始的DataFrame,使用inplace = True
参数:
import pandas as pd
df = pd.read_csv('data.csv')
df.dropna(inplace = True)
print(df.to_string())
Note: 现在,
dropna(inplace = True)
不会返回一个新的DataFrame,但它会从原始DataFrame中删除所有包含NULL值的行。
替换空值
另一种处理空单元格的方法是插入一个新的值。这样,你就不必因为一些空单元格而删除整个行。fillna()
方法允许我们用一个值替换空单元格:
#Replace NULL values with the number 130
import pandas as pd
df = pd.read_csv('data.csv')
df.fillna(130, inplace = True)
只对指定的列进行替换
上面的例子替换了整个数据框架中的所有空单元。要想只替换一列的空值,请指定DataFrame的列名。
代码语言:javascript复制#Replace NULL values in the "Calories" columns with the number 130
import pandas as pd
df = pd.read_csv('data.csv')
df["Calories"].fillna(130, inplace = True)
用平均数、中位数或模式替换
一个常见的替换空单元格的方法,是计算该列的平均值、中位数或模式值。Pandas使用mean()
median()和
mode()`方法来计算指定列的各自数值。
#Calculate the MEAN, and replace any empty values with it:
import pandas as pd
df = pd.read_csv('data.csv')
x = df["Calories"].mean()
df["Calories"].fillna(x, inplace = True)
代码语言:javascript复制Mean = 平均值(所有数值的总和除以数值的数量)。
#Calculate the MEDIAN, and replace any empty values with it:
import pandas as pd
df = pd.read_csv('data.csv')
x = df["Calories"].median()
df["Calories"].fillna(x, inplace = True)
代码语言:javascript复制Median = 在你对所有数值进行升序排序后,他的数值在中间。
#Calculate the MODE, and replace any empty values with it:
import pandas as pd
df = pd.read_csv('data.csv')
x = df["Calories"].mode()[0]
df["Calories"].fillna(x, inplace = True)
Mode = 出现频率最高的值。Cleaning Data of Wrong Format
格式错误的数据
带有错误格式数据的单元格会使数据分析变得困难,甚至是不可能。要解决这个问题,你有两个选择:删除这些行,或者将列中的所有单元格转换成相同的格式。
转换为正确的格式
在我们的数据框架中,有两个单元格的格式是错误的。查看第22行和第26行,"日期 "列应该是一个代表日期的字符串:
代码语言:javascript复制 Duration Date Pulse Maxpulse Calories
0 60 '2020/12/01' 110 130 409.1
1 60 '2020/12/02' 117 145 479.0
2 60 '2020/12/03' 103 135 340.0
3 45 '2020/12/04' 109 175 282.4
4 45 '2020/12/05' 117 148 406.0
5 60 '2020/12/06' 102 127 300.0
6 60 '2020/12/07' 110 136 374.0
7 450 '2020/12/08' 104 134 253.3
8 30 '2020/12/09' 109 133 195.1
9 60 '2020/12/10' 98 124 269.0
10 60 '2020/12/11' 103 147 329.3
11 60 '2020/12/12' 100 120 250.7
12 60 '2020/12/12' 100 120 250.7
13 60 '2020/12/13' 106 128 345.3
14 60 '2020/12/14' 104 132 379.3
15 60 '2020/12/15' 98 123 275.0
16 60 '2020/12/16' 98 120 215.2
17 60 '2020/12/17' 100 120 300.0
18 45 '2020/12/18' 90 112 NaN
19 60 '2020/12/19' 103 123 323.0
20 45 '2020/12/20' 97 125 243.0
21 60 '2020/12/21' 108 131 364.2
22 45 NaN 100 119 282.0
23 60 '2020/12/23' 130 101 300.0
24 45 '2020/12/24' 105 132 246.0
25 60 '2020/12/25' 102 126 334.5
26 60 20201226 100 120 250.0
27 60 '2020/12/27' 92 118 241.0
28 60 '2020/12/28' 103 132 NaN
29 60 '2020/12/29' 100 132 280.0
30 60 '2020/12/30' 102 129 380.3
31 60 '2020/12/31' 92 115 243.0
Pandas有一个to_datetime()
方法来实现这个目的:
import pandas as pd
df = pd.read_csv('data.csv')
df['Date'] = pd.to_datetime(df['Date'])
print(df.to_string())
从结果中你可以看到,第26行的日期是固定的,但是第22行的空日期得到了一个NaT(Not a Time)值,换句话说是一个空值。处理空值的一个方法是简单地删除整个行。
移除行
在上面的例子中,转换的结果给了我们一个NaT值,这可以作为一个NULL值来处理,我们可以通过使用dropna()
方法来删除该行。
#Remove rows with a NULL value in the "Date" column
df.dropna(subset=['Date'], inplace = True)
修复错误的数据
错误的数据
"错误的数据 "不一定是 "空单元格 "或 "错误的格式",它可以只是错误的,比如有人登记了 "199 "而不是 "1.99"。有时,你可以通过查看数据集来发现错误的数据,因为你对它应该是什么有一个期望。如果你看一下我们的数据集,你可以看到在第7行,持续时间是450,但对于其他所有的行,持续时间是在30和60之间。这不一定是错的,但考虑到这是某人的锻炼时间的数据集,我们得出结论,这个人没有在450分钟内锻炼。
代码语言:javascript复制 Duration Date Pulse Maxpulse Calories
0 60 '2020/12/01' 110 130 409.1
1 60 '2020/12/02' 117 145 479.0
2 60 '2020/12/03' 103 135 340.0
3 45 '2020/12/04' 109 175 282.4
4 45 '2020/12/05' 117 148 406.0
5 60 '2020/12/06' 102 127 300.0
6 60 '2020/12/07' 110 136 374.0
7 450 '2020/12/08' 104 134 253.3
8 30 '2020/12/09' 109 133 195.1
9 60 '2020/12/10' 98 124 269.0
10 60 '2020/12/11' 103 147 329.3
11 60 '2020/12/12' 100 120 250.7
12 60 '2020/12/12' 100 120 250.7
13 60 '2020/12/13' 106 128 345.3
14 60 '2020/12/14' 104 132 379.3
15 60 '2020/12/15' 98 123 275.0
16 60 '2020/12/16' 98 120 215.2
17 60 '2020/12/17' 100 120 300.0
18 45 '2020/12/18' 90 112 NaN
19 60 '2020/12/19' 103 123 323.0
20 45 '2020/12/20' 97 125 243.0
21 60 '2020/12/21' 108 131 364.2
22 45 NaN 100 119 282.0
23 60 '2020/12/23' 130 101 300.0
24 45 '2020/12/24' 105 132 246.0
25 60 '2020/12/25' 102 126 334.5
26 60 20201226 100 120 250.0
27 60 '2020/12/27' 92 118 241.0
28 60 '2020/12/28' 103 132 NaN
29 60 '2020/12/29' 100 132 280.0
30 60 '2020/12/30' 102 129 380.3
31 60 '2020/12/31' 92 115 243.0
替换值
修复错误数值的一个方法是用其他东西来代替。在我们的例子中,这很可能是一个打字错误,数值应该是 "45 "而不是 "450",我们可以在第7行插入 "45":
代码语言:javascript复制df.loc[7, 'Duration'] = 45
对于小的数据集,你也许可以一个一个地替换错误的数据,但对于大的数据集则不行。对于较大的数据集,要替换错误的数据,你可以创建一些规则,例如,为合法的值设置一些界限,并替换任何超出界限的值。
代码语言:javascript复制#If the value is higher than 120, set it to 120
for x in df.index:
if df.loc[x, "Duration"] > 120:
df.loc[x, "Duration"] = 120
移除行
另一种处理错误数据的方法是删除包含错误数据的行。这样,你就不必找出用什么来替代它们,而且很有可能你不需要它们来做分析。
代码语言:javascript复制#Delete rows where "Duration" is higher than 120:
for x in df.index:
if df.loc[x, "Duration"] > 120:
df.drop(x, inplace = True)
删除重复的内容
发现重复的内容
重复的行是指已经注册过一次以上的行。
代码语言:javascript复制 Duration Date Pulse Maxpulse Calories
0 60 '2020/12/01' 110 130 409.1
1 60 '2020/12/02' 117 145 479.0
2 60 '2020/12/03' 103 135 340.0
3 45 '2020/12/04' 109 175 282.4
4 45 '2020/12/05' 117 148 406.0
5 60 '2020/12/06' 102 127 300.0
6 60 '2020/12/07' 110 136 374.0
7 450 '2020/12/08' 104 134 253.3
8 30 '2020/12/09' 109 133 195.1
9 60 '2020/12/10' 98 124 269.0
10 60 '2020/12/11' 103 147 329.3
11 60 '2020/12/12' 100 120 250.7
12 60 '2020/12/12' 100 120 250.7
13 60 '2020/12/13' 106 128 345.3
14 60 '2020/12/14' 104 132 379.3
15 60 '2020/12/15' 98 123 275.0
16 60 '2020/12/16' 98 120 215.2
17 60 '2020/12/17' 100 120 300.0
18 45 '2020/12/18' 90 112 NaN
19 60 '2020/12/19' 103 123 323.0
20 45 '2020/12/20' 97 125 243.0
21 60 '2020/12/21' 108 131 364.2
22 45 NaN 100 119 282.0
23 60 '2020/12/23' 130 101 300.0
24 45 '2020/12/24' 105 132 246.0
25 60 '2020/12/25' 102 126 334.5
26 60 20201226 100 120 250.0
27 60 '2020/12/27' 92 118 241.0
28 60 '2020/12/28' 103 132 NaN
29 60 '2020/12/29' 100 132 280.0
30 60 '2020/12/30' 102 129 380.3
31 60 '2020/12/31' 92 115 243.0
通过查看我们的测试数据集,我们可以假设第11和12行是重复的。为了发现重复的数据,我们可以使用duplicated()
方法。duplicated()
方法为每行返回一个布尔值:
#Returns True for every row that is a duplicate, othwerwise False
print(df.duplicated())
删除重复的内容
要删除重复的,使用drop_duplicates()
方法。
#Remove all duplicates:
df.drop_duplicates(inplace = True)
Remember:
(inplace = True)
将确保该方法不会返回一个新的DataFrame,但是它将从原始DataFrame中删除所有重复的部分。