缺失值很常见,并且可能是由于人为错误、仪器错误、来自另一个团队的处理,或者只是缺少特定观察的数据。
在这个字节中,我们将看看如何将 NaN 填充到
DataFrame
,如果您选择通过填充它们来处理 NaN。
首先,让我们创建一个模拟 DataFrame
一些随机值被丢弃:
import numpy as np
array = np.random.randn(25, 3)
mask = np.random.choice([1, 0], array.shape, p=[.3, .7]).astype(bool)
array[mask] = np.nan
df = pd.DataFrame(array, columns=['Col1', 'Col2', 'Col3'])
Col1 Col2 Col3
0 -0.671603 -0.792415 0.783922
1 0.207720 NaN 0.996131
2 -0.892115 -1.282333 NaN
3 -0.315598 -2.371529 -1.959646
4 NaN NaN -0.584636
5 0.314736 -0.692732 -0.303951
6 0.355121 NaN NaN
7 NaN -1.900148 1.230828
8 -1.795468 0.490953 NaN
9 -0.678491 -0.087815 NaN
10 0.755714 0.550589 -0.702019
11 0.951908 -0.529933 0.344544
12 NaN 0.075340 -0.187669
13 NaN 0.314342 -0.936066
14 NaN 1.293355 0.098964
比如说,让我们绘制第三列:
plt.plot(df['Col3'])
当使用各种技术填充时——这个 NaN 填充图可以替换为:
fillna() – 均值、中位数、众数
您可以将这些值填充到新列中并将其分配给您要填充的列,或者使用 inplace
争论。 在这里,我们将在新列中提取填充值以便于检查:
mean = df['Col3'].fillna(df['Col3'].mean(), inplace=False)
median = df['Col3'].fillna(df['Col3'].median(), inplace=False)
mode = df['Col3'].fillna(df['Col3'].mode(), inplace=False)
列的中位数、均值和众数为 -0.187669
, -0.110873
和 0.000000
这些值将分别用于每个 NaN。 这有效地填充了常量值,其中输入的值取决于列的整体。
首先,用中值填充会导致:
平均值:
使用模式值:
fillna() – 常量值
你也可以用一个常数值代替:
查看我们的 Git 学习实践指南,其中包含最佳实践、行业认可的标准以及随附的备忘单。 停止谷歌搜索 Git 命令,实际上 学习 它!
constant = df['Col3'].fillna(0, inplace=False
这导致放置一个常数值 (0) 而不是每个 NaN。 0
接近我们的中位数和均值并且等于众数,因此填充的值将非常类似于我们的模拟数据集的该方法:
0 0.783922
1 0.996131
2 0.000000
3 -1.959646
4 -0.584636
5 -0.303951
6 0.000000
7 1.230828
8 0.000000
9 0.000000
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
fillna() - 向前和向后填充
在每一行上——您可以进行前向或后向填充,从之前或之后的行中获取值:
ffill = df['Col3'].fillna(method='ffill')
bfill = df['Col3'].fillna(method='bfill')
使用前向填充,因为我们从第 2 行中丢失了——第 1 行的值被用来填充第二行。 值向前传播:
0 0.783922
1 0.996131
2 0.996131
3 -1.959646
4 -0.584636
5 -0.303951
6 -0.303951
7 1.230828
8 1.230828
9 1.230828
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
对于反向填充,会发生相反的情况。 第 2 行用第 3 行的值填充:
0 0.783922
1 0.996131
2 -1.959646
3 -1.959646
4 -0.584636
5 -0.303951
6 1.230828
7 1.230828
8 -0.702019
9 -0.702019
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
不过,如果有不止一个 NaN
在一个序列中——这些不会很好,并且可以进一步向下级联 NaN,扭曲数据并删除实际记录的值。
插()
interpolate()
方法将值的插值委托给 SciPy 用于插值的一套方法. 它接受各种各样的论点,包括, nearest
, zero
, slinear
, quadratic
, cubic
, spline
, barycentric
, polynomial
, krogh
, piecewise_polynomial
, spline
, pchip
, akima
, cubicspline
等等。
插值比仅使用常量或半变量(例如以前的方法)填充值更加灵活和“智能”。
插值可以以其他方法无法做到的方式正确填充序列,例如:
s = pd.Series([0, 1, np.nan, np.nan, np.nan, 5])
s.fillna(s.mean()).values
s.fillna(method='ffill').values
s.interpolate().values
默认插值是线性的,并假设 1...5
很可能是 1, 2, 3, 4, 5
序列并不牵强(但不能保证)。 恒定填充和向前或向后填充都在这里惨遭失败。 一般来说,当涉及到在噪声信号或损坏的数据集中填充 NaN 时,插值通常会成为一个好朋友。
尝试插值类型可能会产生更好的结果。
这里有两种插值方法(splice
和 polynomial
需要一个 order
争论):
nearest = df['Col3'].interpolate(method='nearest')
polynomial = df['Col3'].interpolate(method='polynomial', order=3)
这些导致:
和: