在熊猫的数据框中查找非数字行?

我在大熊猫中有一个很大的数据框,除了用作索引的列之外,它应该只有数值:

df = pd.DataFrame({'a': [1, 2, 3, 'bad', 5],
'b': [0.1, 0.2, 0.3, 0.4, 0.5],
'item': ['a', 'b', 'c', 'd', 'e']})
df = df.set_index('item')

如何找到数据帧 df中包含非数值的行?

在这个示例中,它是 dataframe 中的第四行,在 a列中有字符串 'bad'。如何以编程方式找到此行?

153677 次浏览

很抱歉造成了混乱,这应该是正确的方法。您是想只捕获 'bad',而不是像 'good'这样的东西; 还是只捕获任何非数值值?

In[15]:
np.where(np.any(np.isnan(df.convert_objects(convert_numeric=True)), axis=1))
Out[15]:
(array([3]),)

您可以使用 np.isreal检查每个元素的类型(应用地图对 DataFrame 中的每个元素应用一个函数) :

In [11]: df.applymap(np.isreal)
Out[11]:
a     b
item
a      True  True
b      True  True
c      True  True
d     False  True
e      True  True

如果行中的所有内容都为 True,那么它们都是数字:

In [12]: df.applymap(np.isreal).all(1)
Out[12]:
item
a        True
b        True
c        True
d       False
e        True
dtype: bool

因此,为了得到胭脂的 subDataFrame,(注意: 上面的否定,~ ,会找到那些至少有一个流氓非数字的) :

In [13]: df[~df.applymap(np.isreal).all(1)]
Out[13]:
a    b
item
d     bad  0.4

你也可以找到犯罪者的位置,你可以使用 Argmin:

In [14]: np.argmin(df.applymap(np.isreal).all(1))
Out[14]: 'd'

正如 @ CTZhu所指出的,对于 检查它是否是,int 或 float 可能稍微快一些(np.isreal 有一些额外的开销) :

df.applymap(lambda x: isinstance(x, (int, float)))

这个问题已经有了一些很好的答案,但是这里有一个很好的片段,我经常使用它来删除一些列上有非数字值的行:

# Eliminate invalid data from dataframe (see Example below for more context)


num_df = (df.drop(data_columns, axis=1)
.join(df[data_columns].apply(pd.to_numeric, errors='coerce')))


num_df = num_df[num_df[data_columns].notnull().all(axis=1)]

这样做的方法是,我们首先从 df中取出所有的 data_columns,然后使用 join在它们通过 pd.to_numeric之后将它们放回原处(使用选项 'coerce',这样所有非数字条目都被转换为 NaN)。结果保存到 num_df

在第二行,我们使用一个过滤器,它只保留所有值不为空的行。

请注意,pd.to_numeric强制将所有不能转换为数值的内容转换为 NaN,因此表示数值的字符串不会被删除。例如,'1.25'将被识别为数值 1.25

免责声明: pd.to_numeric是在熊猫版本 0.17.0中引入的

例如:

In [1]: import pandas as pd


In [2]: df = pd.DataFrame({"item": ["a", "b", "c", "d", "e"],
...:                    "a": [1,2,3,"bad",5],
...:                    "b":[0.1,0.2,0.3,0.4,0.5]})


In [3]: df
Out[3]:
a    b item
0    1  0.1    a
1    2  0.2    b
2    3  0.3    c
3  bad  0.4    d
4    5  0.5    e


In [4]: data_columns = ['a', 'b']


In [5]: num_df = (df
...:           .drop(data_columns, axis=1)
...:           .join(df[data_columns].apply(pd.to_numeric, errors='coerce')))


In [6]: num_df
Out[6]:
item   a    b
0    a   1  0.1
1    b   2  0.2
2    c   3  0.3
3    d NaN  0.4
4    e   5  0.5


In [7]: num_df[num_df[data_columns].notnull().all(axis=1)]
Out[7]:
item  a    b
0    a  1  0.1
1    b  2  0.2
2    c  3  0.3
4    e  5  0.5

如果使用具有字符串值的列,可以使用 非常有用的函数 Series es.str.isnumeric () :

a = pd.Series(['hi','hola','2.31','288','312','1312', '0,21', '0.23'])

我要做的是将该列复制到新列,然后执行 str.place (’)和 str.place (’,’,”) ,然后选择数值。 以及:

a = a.str.replace('.','')
a = a.str.replace(',','')
a.str.isnumeric()

出局[15] : 0错 1错 2真 3真 4真 5真 6真 7真 Dtype: bool

祝大家好运!

# Original code
df = pd.DataFrame({'a': [1, 2, 3, 'bad', 5],
'b': [0.1, 0.2, 0.3, 0.4, 0.5],
'item': ['a', 'b', 'c', 'd', 'e']})
df = df.set_index('item')

使用‘ coance’转换为数字 ,这将用‘ nan’填充不良值

a = pd.to_numeric(df.a, errors='coerce')

使用 Isna返回一个布尔索引:

idx = a.isna()

将该索引应用于数据框架:

df[idx]

输出

返回包含错误数据的行:

        a    b
item
d     bad  0.4

我认为,只要给出一个想法,把列转换成字符串,处理字符串更容易。但是,这不适用于包含数字的字符串,如 bad123。而 ~是选择的补充。

df['a'] = df['a'].astype(str)
df[~df['a'].str.contains('0|1|2|3|4|5|6|7|8|9')]
df['a'] = df['a'].astype(object)

并使用 '|'.join([str(i) for i in range(10)])生成 '0|1|...|8|9'

或者使用 np.isreal()函数,就像投票最多的答案一样

df[~df['a'].apply(lambda x: np.isreal(x))]

您是否使用. astype ()转换了数据?

以上所有的好评论必须解决99% 的情况,但如果您仍然有麻烦,请也检查是否转换了您的数据类型。

有时我强制数据键入 float16以节省内存。使用:

df[col] = df[col].astype(np.float16)

但这可能会悄悄地破坏您的代码。因此,如果您进行了任何类型的数据类型转换,请再次检查 溢出。禁用转换并重试。

我成功了!