Pandas - 处理分类数据中的 NaN
Pandas - Handling NaNs in categorical data
我在数据框中有一列包含分类数据,但缺少一些数据,即 NaN。我想对这些数据进行线性插值以填充缺失值,但我不确定如何去做。我不能删除 NaN 以将数据转换为分类类型,因为我需要填充它们。一个简单的例子来演示我正在尝试做什么。
col1 col2
5 cloudy
3 windy
6 NaN
7 rainy
10 NaN
假设我想将 col2
转换为分类数据但保留 NaN 并使用线性插值填充它们我该怎么做。可以说在将列转换为分类数据后它看起来像这样
col2
1
2
NaN
3
NaN
然后我可以做线性插值得到这样的结果
col2
1
2
3
3
2
我怎样才能做到这一点?
更新:
Is there a way to convert the data back to its original form after
interpolation ie instead of 1,2 or 3 you have cloudy,windy and rainy
again?
解决方法:我特意在你原来的 DF 中添加了更多行:
In [129]: df
Out[129]:
col1 col2
0 5 cloudy
1 3 windy
2 6 NaN
3 7 rainy
4 10 NaN
5 5 cloudy
6 10 NaN
7 7 rainy
In [130]: df.dtypes
Out[130]:
col1 int64
col2 category
dtype: object
In [131]: df.col2 = (df.col2.cat.codes.replace(-1, np.nan)
...: .interpolate().astype(int).astype('category')
...: .cat.rename_categories(df.col2.cat.categories))
...:
In [132]: df
Out[132]:
col1 col2
0 5 cloudy
1 3 windy
2 6 rainy
3 7 rainy
4 10 cloudy
5 5 cloudy
6 10 cloudy
7 7 rainy
旧"numerical"答案:
IIUC 你可以这样做:
In [66]: df
Out[66]:
col1 col2
0 5 cloudy
1 3 windy
2 6 NaN
3 7 rainy
4 10 NaN
首先让我们分解 col2
:
In [67]: df.col2 = pd.factorize(df.col2, na_sentinel=-2)[0] + 1
In [68]: df
Out[68]:
col1 col2
0 5 1
1 3 2
2 6 -1
3 7 3
4 10 -1
现在我们可以对其进行插值(将 -1
替换为 NaN
):
In [69]: df.col2.replace(-1, np.nan).interpolate().astype(int)
Out[69]:
0 1
1 2
2 2
3 3
4 3
Name: col2, dtype: int32
相同的方法,但将内插序列转换为 category
dtype:
In [70]: df.col2.replace(-1, np.nan).interpolate().astype(int).astype('category')
Out[70]:
0 1
1 2
2 2
3 3
4 3
Name: col2, dtype: category
Categories (3, int64): [1, 2, 3]
我知道你要求线性插值,但如果你想这样做,这只是另一种方法easier.As将类别转换为数字不是一个好主意,我建议这个。
您可以简单地使用 pandas 库中的插值方法和 'pad' 方法,例如:
df.interpolate(method='pad')
您还可以在 here 中查看其他方法和使用它们的示例。 (link 是 pandas 插值的文档)
我在数据框中有一列包含分类数据,但缺少一些数据,即 NaN。我想对这些数据进行线性插值以填充缺失值,但我不确定如何去做。我不能删除 NaN 以将数据转换为分类类型,因为我需要填充它们。一个简单的例子来演示我正在尝试做什么。
col1 col2
5 cloudy
3 windy
6 NaN
7 rainy
10 NaN
假设我想将 col2
转换为分类数据但保留 NaN 并使用线性插值填充它们我该怎么做。可以说在将列转换为分类数据后它看起来像这样
col2
1
2
NaN
3
NaN
然后我可以做线性插值得到这样的结果
col2
1
2
3
3
2
我怎样才能做到这一点?
更新:
Is there a way to convert the data back to its original form after interpolation ie instead of 1,2 or 3 you have cloudy,windy and rainy again?
解决方法:我特意在你原来的 DF 中添加了更多行:
In [129]: df
Out[129]:
col1 col2
0 5 cloudy
1 3 windy
2 6 NaN
3 7 rainy
4 10 NaN
5 5 cloudy
6 10 NaN
7 7 rainy
In [130]: df.dtypes
Out[130]:
col1 int64
col2 category
dtype: object
In [131]: df.col2 = (df.col2.cat.codes.replace(-1, np.nan)
...: .interpolate().astype(int).astype('category')
...: .cat.rename_categories(df.col2.cat.categories))
...:
In [132]: df
Out[132]:
col1 col2
0 5 cloudy
1 3 windy
2 6 rainy
3 7 rainy
4 10 cloudy
5 5 cloudy
6 10 cloudy
7 7 rainy
旧"numerical"答案:
IIUC 你可以这样做:
In [66]: df
Out[66]:
col1 col2
0 5 cloudy
1 3 windy
2 6 NaN
3 7 rainy
4 10 NaN
首先让我们分解 col2
:
In [67]: df.col2 = pd.factorize(df.col2, na_sentinel=-2)[0] + 1
In [68]: df
Out[68]:
col1 col2
0 5 1
1 3 2
2 6 -1
3 7 3
4 10 -1
现在我们可以对其进行插值(将 -1
替换为 NaN
):
In [69]: df.col2.replace(-1, np.nan).interpolate().astype(int)
Out[69]:
0 1
1 2
2 2
3 3
4 3
Name: col2, dtype: int32
相同的方法,但将内插序列转换为 category
dtype:
In [70]: df.col2.replace(-1, np.nan).interpolate().astype(int).astype('category')
Out[70]:
0 1
1 2
2 2
3 3
4 3
Name: col2, dtype: category
Categories (3, int64): [1, 2, 3]
我知道你要求线性插值,但如果你想这样做,这只是另一种方法easier.As将类别转换为数字不是一个好主意,我建议这个。
您可以简单地使用 pandas 库中的插值方法和 'pad' 方法,例如:
df.interpolate(method='pad')
您还可以在 here 中查看其他方法和使用它们的示例。 (link 是 pandas 插值的文档)