首页 > 解决方案 > 为什么在 Python Pandas 中,浮点条件可以删除数据框中的对象?

问题描述

数据集:

你好。请根据著名的 Iris 数据集考虑以下代码:

# Import : 
from sklearn.datasets import load_iris
import pandas as pd

# Dataset preview : 
dataset=load_iris()
df=pd.DataFrame(dataset['data'],columns=['Petal length','Petal Width','Sepal Length','Sepal Width'])
df['Species']=dataset['target']
df['Species']=df['Species'].apply(lambda x: dataset['target_names'][x])
df.head()

Output : 
Petal length Petal Width Sepal Length Sepal Width Species
0   5.1     3.5     1.4     0.2     setosa
1   4.9     3.0     1.4     0.2     setosa
2   4.7     3.2     1.3     0.2     setosa
3   4.6     3.1     1.5     0.2     setosa
4   5.0     3.6     1.4     0.2     setosa

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
Petal length    150 non-null float64
Petal Width     150 non-null float64
Sepal Length    150 non-null float64
Sepal Width     150 non-null float64
Species         150 non-null object

问题发生:

当我根据数字条件过滤数据框时,非数字列的值(这里Species是 an object)被删除,见下文:

col = ['Petal length','Petal Width','Sepal Length','Sepal Width']
df2 = df[df[col] < 5]
df2.info()
Output : 
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
Petal length    22 non-null float64
Petal Width     150 non-null float64
Sepal Length    104 non-null float64
Sepal Width     150 non-null float64
Species         0 non-null object

df2.head()
Output : 
    Petal length    Petal Width     Sepal Length    Sepal Width     Species
0   NaN     3.5     1.4     0.2     NaN
1   4.9     3.0     1.4     0.2     NaN
2   4.7     3.2     1.3     0.2     NaN
3   4.6     3.1     1.5     0.2     NaN
4   NaN     3.6     1.4     0.2     NaN

问题 :

如您所见,Species列变为0 non-null object且仅NaN。我确定我在我的情况下做错了什么,但我不明白是什么。 -> 我怎样才能使这个条件和保持Species值不被删除?

非常感谢您的帮助

标签: pythonpandasfilterconditional-operator

解决方案


别担心,这很容易解决。要了解发生了什么,请查看df[col] < 5.

这是一个易于运行的示例,应该可以演示该问题:

import pandas as pd

df = pd.DataFrame(data={'col_1': [1, 2, 3, 4, 5], 'col_2': [5, 4, 3, 2, 1], 'col_3': [19, 18, 2, 17, 20]})
print(f'df:\n{df}\n')

cols_to_filter = ['col_1', 'col_3']

mask_1 = df[cols_to_filter] < 3
print(f'mask_1:\n{mask_1}\n')

mask_2 = (df[cols_to_filter] < 3).any(axis='columns')
print(f'mask_2:\n{mask_2}\n')

res_df_1 = df[mask_1]
print(f'res_df_1:\n{res_df_1}\n')

res_df_2 = df[mask_2]
print(f'res_df_2:\n{res_df_2}\n')

以下是程序的各种输出:

df:
   col_1  col_2  col_3
0      1      5     19
1      2      4     18
2      3      3      2
3      4      2     17
4      5      1     20

mask_1:
   col_1  col_3
0   True  False
1   True  False
2  False   True
3  False  False
4  False  False

mask_2:
0     True
1     True
2     True
3    False
4    False
dtype: bool

res_df_1:
   col_1  col_2  col_3
0    1.0    NaN    NaN
1    2.0    NaN    NaN
2    NaN    NaN    2.0
3    NaN    NaN    NaN
4    NaN    NaN    NaN

res_df_2:
   col_1  col_2  col_3
0      1      5     19
1      2      4     18
2      3      3      2

要解决此问题,您可以使用df[(df[col] < 5).any(axis='columns')]df[(df[col] < 5).all(axis='columns')],具体取决于您要执行的操作。


我忍不住要调整你的程序。有几个替代方案.apply(),这个应该是最好的。

import pandas as pd
from sklearn.datasets import load_iris

dataset = load_iris()
df = pd.DataFrame(dataset['data'], columns=['Petal length', 'Petal Width', 'Sepal Length', 'Sepal Width'])
df['Species'] = dataset['target_names'][dataset['target']]

推荐阅读